Вызов кода JavaScript в iframe с родительской страницы

в принципе, у меня есть iframe встроенный в страницу и iframe некоторые JavaScript процедуры, которые мне нужно вызвать с родительской страницы.

теперь наоборот довольно просто, как вам нужно только позвонить parent.functionName(), но, к сожалению, мне нужно именно наоборот.

обратите внимание, что моя проблема не меняется источник URL-адресом на iframe, но вызов функции, определенной в iframe.

17 ответов


предположим, что идентификатор вашего 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(); 

есть некоторые особенности, чтобы быть в курсе здесь.

  1. HTMLIFrameElement.contentWindow вероятно, это более простой способ, но это не совсем стандартное свойство, и некоторые браузеры не поддерживают его, в основном более старые. Это связано с тем, что стандарт DOM Level 1 HTML ничего не говорит о


вызов функции JS из iframe возможно, но только когда и родитель, и страница загружены в iframe из того же домена, т. е. abc.com, и оба используют один и тот же протокол, т. е. оба либо на http:// или https://.

вызов завершится неудачей в указанных ниже случаях:

  1. родительская страница и страница iframe из разных доменов.
  2. они используют разные протоколы, один находится на http://, а другой-на протокол https.//:

любое обходное решение этого ограничения было бы крайне небезопасным.

например, представьте, что я зарегистрировал домен superwinningcontest.com и разослал ссылки на электронные письма людей. Когда они загрузили главную страницу, Я мог скрыть несколько iframes там и читать их фид Facebook, проверить последние транзакции Amazon или PayPal, или-если они использовали службу, которая не реализовала достаточную безопасность-перевести деньги из своих счетов. Вот почему JavaScript ограничен тем же доменом и тем же протоколом.


в IFRAME сделайте свою функцию общедоступной для объекта window:

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

для доступа с родительской страницы используйте следующее:

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

Если 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 (так как это был документ XHTML 1.1). Вот как это работает с объектами:

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

(извините за уродливые разрывы строк, не поместились в одну строку)


IFRAME должен быть в frames[] коллекция. Используйте что-то вроде

frames['iframeid'].method();

англ. была после этого.

поскольку страница теперь сломана и доступна только через archive.org, я воспроизвел его здесь:

IFrames

на этой странице Я даю краткий обзор доступа к iframes со страницы, на которой они находятся. Неудивительно, что есть некоторые соображения браузера.

iframe-это встроенный фрейм, фрейм, содержащий полностью отдельную страницу с собственным URL-адресом, тем не менее помещается внутри другой HTML-страницы. Это дает очень хорошие возможности в веб-дизайне. Проблема заключается в доступе к iframe, например, для загрузки в него новой страницы. На этой странице объясняется, как это сделать.

кадр или объект?

основной вопрос заключается в том, рассматривается ли iframe как фрейм или как объект.

  • как пояснили на введение в рамки страницы, если вы используете фреймы браузер создает иерархию кадров для вас (top.frames[1].frames[2] и такие). Вписывается ли iframe в эту иерархию фреймов?
  • или браузер видит iframe как просто другой объект, объект, который имеет свойство src? В этом случае мы должны использовать стандартный DOM call (типа document.getElementById('theiframe')) для доступа к нему. В общем, браузеры разрешают оба представления на "реальных" (жестко закодированных) iframes, но сгенерированные iframes не могут быть доступны в качестве кадров.

имя атрибут

самое важное правило-дать любой iframe, который вы создаете name атрибут, даже если вы также используете id.

<iframe src="iframe_page1.html"
    id="testiframe"
    name="testiframe"></iframe>

большинство браузеров нужны name атрибут, чтобы сделать iframe частью иерархии кадров. Некоторые браузеры (особенно Mozilla) нуждаются в id чтобы сделать iframe доступным в качестве объекта. Назначая оба атрибута iframe, вы сохраняете свои параметры открытыми. Но!--4--> гораздо важнее, чем id.

открыть

либо вы получаете доступ к iframe в качестве объекта и меняете его src или вы получаете доступ к iframe в качестве кадра и меняете его location.href.

документ.getElementById ('iframe_id').src = ' newpage.HTML-код'; frames ['iframe_name'].местоположение.href = ' newpage.HTML-код'; Синтаксис фрейма несколько предпочтительнее, поскольку Opera 6 поддерживает его, но не синтаксис объекта.

доступ к элемент iframe

поэтому для полного кросс-браузера вы должны дать iframe имя и использовать

frames['testiframe'].location.href

синтаксис. Насколько я знаю, это всегда срабатывает.

доступ к документу

доступ к документу внутри iframe довольно прост, если вы используете . Подсчет количества ссылок в документе в iframe, делать frames['testiframe'].document.links.length.

генерируемые iframes

когда вы создаете iframe через W3C DOM iframe не сразу вводится в frames массив, однако, и frames['testiframe'].location.href синтаксис не будет работать сразу. Браузеру нужно немного времени, прежде чем iframe появится в массиве, время, в течение которого сценарий не может выполняться.

на document.getElementById('testiframe').src синтаксис отлично работает во всех обстоятельства.

на target атрибут ссылки не работает ни с сгенерированными iframes, кроме как в Opera, хотя я дал сгенерированный iframe как name и id.

отсутствие target поддержка означает, что вы должны использовать JavaScript для изменения содержимого сгенерированного iframe, но поскольку вам все равно нужен JavaScript для его создания, я не вижу в этом большой проблемы.

размер текста в iframes

любопытный Explorer 6 только ошибка:

при изменении размера текста через меню Вид размеры текста в iframes правильно изменены. Однако этот браузер не изменяет разрывы строк в исходном тексте, так что часть текста может стать невидимой, или разрывы строк могут произойти, пока строка может содержать другое слово.


Я нашел довольно элегантное решение.

Как вы сказали, довольно легко выполнить код, расположенный в Родительском документе. И это основа моего кода, делай как раз наоборот.

при загрузке iframe я вызываю функцию, расположенную в Родительском документе, передавая в качестве аргумента ссылку на локальную функцию, расположенную в документе iframe. Родительский документ теперь имеет прямой доступ к функции iframe через это ссылка.

пример:

на родителя:

function tunnel(fn) {
    fn();
}

в iframe:

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

parent.tunnel(myFunction);

когда iframe загружается, он будет вызывать parent.туннель (YourFunctionReference), который будет выполнять функцию, полученную в параметре.

это просто, без необходимости иметь дело со всеми нестандартными методами из различных браузеров.


некоторые из этих ответов не затрагивают проблему 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','*')

продолжение JoelAnair это ответ:

для большей надежности используйте следующее:

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

if(el.contentWindow)
{
   el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
   el.contentDocument.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();
...

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

же самое, но немного легче будет!--3-->как обновить родительскую страницу со страницы в iframe. Просто вызовите функцию родительской страницы, чтобы вызвать функцию javascript для перезагрузки страницы:

window.location.reload();

или сделайте это прямо со страницы в iframe:

window.parent.location.reload();

обе работы.


Если мы хотим вызвать функцию javascript родительской страницы из iframe, который генерируется из кодирования. ex shadowbox или lightbox


попробуйте просто parent.myfunction()


используйте following для вызова функции фрейма на родительской странице

parent.document.getElementById('frameid').contentWindow.somefunction()