Вызов кода 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();
есть некоторые особенности, чтобы быть в курсе здесь.
HTMLIFrameElement.contentWindowвероятно, это более простой способ, но это не совсем стандартное свойство, и некоторые браузеры не поддерживают его, в основном более старые. Это связано с тем, что стандарт DOM Level 1 HTML ничего не говорит о
вызов функции JS из
iframeвозможно, но только когда и родитель и страница загружены вiframeиз того же домена, т. е. abc.com, и оба используют один и тот же протокол, т. е. оба находятся либо наhttp://илиhttps://.вызов не будет выполнен в следующих случаях:
- родительская страница и страница iframe находятся в разных доменах.
- они используют разные протоколы, один находится на 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 и содержащий его документ находятся в другом домене, ранее опубликованные методы могут не работать, но есть решение:
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); } } }этот скрипт сначала проверяет домен является ожидаемым доменом, а затем смотрит на сообщение, которое он либо отображает пользователю, либо отвечает, отправляя сообщение обратно в документ, который отправил сообщение в первую очередь.
просто для записи, я столкнулся с той же проблемой сегодня, но на этот раз страница была встроена в объект, а не iframe (так как это был документ XHTML 1.1). Вот как это работает с объектами:
document .getElementById('targetFrame') .contentDocument .defaultView .targetFunction();(извините за уродливые разрывы строк, не вписался в одну строку)
Quirksmode был после этого.
так как страница теперь сломана и доступна только через 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, который вы держите свои варианты открытыми. Ноnameгораздо важнее, чемid.открыть
либо вы получаете доступ к iframe как к объекту и меняете его
srcили вы получаете доступ к iframe в качестве кадра и изменить егоlocation.href.документ.getElementById ('iframe_id').src = ' newpage.HTML-код'; кадры['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 появится в массиве, время, в течение которого ни один скрипт не может работать.The
document.getElementById('testiframe').srcсинтаксис отлично работает во всех обстоятельства.The
targetатрибут ссылки не работает ни с сгенерированными iframes, за исключением Opera, хотя я дал свой сгенерированный iframe какnameиid.отсутствие
targetподдержка означает, что вы должны использовать JavaScript для изменения содержимого сгенерированного iframe, но поскольку вам все равно нужен JavaScript, чтобы сгенерировать его в первую очередь, я не вижу в этом большой проблемы.размер текста в фреймы
любопытный исследователь 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(); ...
же самое, но немного легче будет!--3-->как обновить родительскую страницу со страницы в iframe. Просто вызовите функцию родительской страницы, чтобы вызвать функцию javascript для перезагрузки страницы:
window.location.reload();или сделать это прямо со страницы в iframe:
window.parent.location.reload();обе работы.
Если мы хотим вызвать функцию javascript родительской страницы из iframe, который генерируется из кодирования. ex shadowbox или lightbox
используйте following для вызова функции фрейма в родительской странице
parent.document.getElementById('frameid').contentWindow.somefunction()
Comments