Как получить доступ к родительскому iframe из JavaScript

Что ж, у меня есть IFrame, который вызывает ту же страницу домена. Моя проблема в том, что я хочу получить доступ к некоторой информации из этого родительского iframe с этой вызываемой страницы (из JavaScript). Как я могу получить доступ к этому iframe?

Подробности: есть несколько таких же фреймов iframe, которые могут загружать одну и ту же страницу, потому что я программирую среду Windows. Я намерен закрыть этот Iframe, поэтому мне нужно знать, что я должен закрыть изнутри него. У меня есть массив, содержащий ссылки на эти фреймы.

РЕДАКТИРОВАТЬ: iframe генерируются динамически


person José Leal    schedule 01.06.2009    source источник
comment
даже если фреймы создаются динамически, вы можете назначить новый уникальный идентификатор, используя какой-то счетчик, наконец, вам не нужно знать идентификатор, но вы можете легко искать, см. мой ответ.   -  person Akash Kava    schedule 21.06.2012


Ответы (8)


Также вы можете установить для имени и идентификатора равные значения.

<iframe id="frame1" name="frame1" src="any.html"></iframe>

так что вы сможете использовать следующий код внутри дочерней страницы

parent.document.getElementById(window.name);
person Aquatic    schedule 01.06.2009
comment
Возможно, это не очевидно для всех, но с помощью этого метода вы можете получить доступ к объекту библиотеки родителя (только если родитель уже загрузил библиотеку). Пример: доступ к jQuery с помощью parent. $ ('# Something') - person Zsolti; 31.10.2013
comment
Это решение совместимо с режимом совместимости IE5 +. - person Slayner; 19.04.2016
comment
Даже в 2016 году это отлично работает как часть решения проблемы, когда IE печатает содержимое слишком маленького iframe. Но почему это работает? window.name возвращает строку. Чем отличается использование window.name от простой передачи имени идентификатора в виде строки, которая не работает.)? - person Karl; 02.10.2016
comment
Привет, он не работает с Chrome 59 ..: VM111: 1 Uncaught DOMException: заблокировал фрейм с источником xxx от доступа к фрейм с перекрестным началом. - person Didier68; 28.07.2017
comment
Chrome видит файлы в той же папке, что и кросс-источник, если не установлен CORS. Говорят, это для безопасности. Для настройки CORS нужен сервер. Сообщите пользователям о необходимости настроить сервер или сменить браузер, если обнаружен Chrome. - person ; 17.08.2019

Просто вызовите window.frameElement со своей страницы с фреймами. Если страница не во фрейме, тогда frameElement будет null.

Другой способ (размещение элемента окна внутри фрейма менее тривиально), но для полноты картины:

/**
 * @param f, iframe or frame element
 * @return Window object inside the given frame
 * @effect will append f to document.body if f not yet part of the DOM
 * @see Window.frameElement
 * @usage myFrame.document = getFramedWindow(myFrame).document;
 */
function getFramedWindow(f)
{
    if(f.parentNode == null)
        f = document.body.appendChild(f);
    var w = (f.contentWindow || f.contentDocument);
    if(w && w.nodeType && w.nodeType==9)
        w = (w.defaultView || w.parentWindow);
    return w;
}
person Ian Carter    schedule 28.05.2012
comment
Спасибо! Работает в IE 6+, FF и Chrome! - person rustyx; 04.03.2014
comment
window.frameElement возвращает null, когда окно и iframe имеют разные домены, то есть обмен сообщениями между источниками. - person Qwerty; 06.06.2016
comment
@Qwerty Вы нашли какое-нибудь решение? - person Ajay Patidar; 27.06.2020
comment
@AjayPatidar Думаю, я сдался. :( - person Qwerty; 01.07.2020
comment
@Qwerty Одно из возможных решений - использовать iframe в качестве прокси для отправки сообщений между страницами в разных доменах. sysend.js делает это, например, с помощью postMessage(). - person Anderson Green; 06.02.2021

Я бы рекомендовал использовать postMessage API.

В вашем iframe вызовите:

window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');

На странице, в которую вы включаете iframe, вы можете отслеживать такие события:

window.addEventListener('message', function(event) {
      if(event.origin === 'http://localhost/')
      {
        alert('Received message: ' + event.data.message);
      }
      else
      {
        alert('Origin not allowed!');
      }

    }, false);

Кстати, также можно делать вызовы в другие окна, а не только в iframe.

Дополнительные сведения об API postMessage см. В блоге Джона Ресигса, здесь

person Kenneth Lynne    schedule 24.03.2013
comment
Я думаю, что это явно лучший ответ, содержимое <iframe> не должно ничего знать о родителе, и наоборот. Им нужно только подчиняться контракту простого сообщения. Потрясающие! - person mfeineis; 05.06.2014
comment
‹Iframe› все еще должен знать родительский домен, верно? - person Homr Zodyssey; 01.06.2016
comment
@HomrZodyssey Родительский домен доступен только как механизм безопасности, если он не известен, вы можете установить '*'. - person Amir Ali Akbari; 01.11.2017
comment
Используйте '*' на клиентах. Любые другие решения дают ошибку в браузере Chrome, обрабатывающем файлы в папке клиентов как не являющиеся тем же источником, потому что сервер не настроен. Это лучшее и единственное решение: dyn-web.com / tutorials / iframes / postmessage - person ; 17.08.2019

Старый вопрос, но у меня была такая же проблема, и я нашел способ получить iframe. Это просто вопрос перебора массива frames [] родительского окна и тестирования contentWindow каждого фрейма в сравнении с окном, в котором выполняется ваш код. Пример:

var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
  if (arrFrames[i].contentWindow === window) alert("yay!");
}

Или, используя jQuery:

parent.$("iframe").each(function(iel, el) {
  if(el.contentWindow === window) alert("got it");
});

Этот метод сохраняет присвоение идентификатора каждому iframe, что хорошо в вашем случае, поскольку они создаются динамически. Я не смог найти более прямого пути, поскольку вы не можете получить элемент iframe с помощью window.parent - он переходит прямо к элементу родительского окна (пропуская iframe). Так что просмотр их кажется единственным способом, если вы не хотите использовать идентификаторы.

person ingredient_15939    schedule 10.10.2010
comment
Обновление: это не сработало точно так, как рекламировалось, и мне пришлось использовать документ contentWindow.document ===. Понятия не имею почему. Также в некоторых браузерах я использовал contentDocument. Что ж, мне это нравится! - person Christophe; 06.05.2011
comment
Извините, по общему признанию, я тестировал его только в Firefox. :) Однако я успешно использовал метод jQuery и contentWindow во многих браузерах. - person ingredient_15939; 23.08.2011
comment
Обновление: я узнал, что вы также можете использовать window.frameElement, но я не уверен, какие браузеры его поддерживают. - person Christophe; 09.12.2011
comment
Я не думаю, что такие вещи больше работают; вы получаете ошибку перекрестного происхождения. - person Andrew Mao; 03.06.2014
comment
@AndrewMao вопрос касается документов одного и того же происхождения, поэтому нет причин для проблем с перекрестным происхождением. - person Christophe; 23.09.2015

вы можете использовать parent для доступа к родительской странице. Итак, чтобы получить доступ к функции, это будет:

var obj = parent.getElementById('foo');
person kemiller2002    schedule 01.06.2009
comment
Кевин, проблема в том, чтобы ЗНАТЬ идентификатор. У меня несколько фреймов iframe, и я хочу получить к ним доступ из кода внутри - person José Leal; 01.06.2009
comment
По-прежнему блокируется кадр с источником other-localhost: 8000 от доступа к кадру с перекрестным источником. - person user2568374; 10.05.2018

После установки идентификатора iframe вы можете получить доступ к iframe из внутреннего документа, как показано ниже.

var iframe = parent.document.getElementById(frameElement.id);

Хорошо работает в IE, Chrome и FF.

person Akash Kava    schedule 21.06.2012
comment
Это кажется запутанным способом сделать var iframe = frameElement - person Oriol; 05.12.2015
comment
frameElement возвращает объект в контексте текущего окна, но parent.document.getElementById (frameElement.id) возвращает объект в контексте родительского окна, вы не можете запускать функции javascript родительского окна с помощью frameElement, попробуйте его в jsfiddle и дайте мне и пример, если можете . - person Akash Kava; 05.12.2015

Может просто использовать

window.parent

в ваш iframe, чтобы получить вызывающий фрейм / окна. Если у вас было несколько кадров вызова, вы можете использовать

window.top
person Clawfire    schedule 28.11.2011

Попробуйте это, в родительском фрейме настройте IFRAME следующим образом:

<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>

Обратите внимание, что идентификатор каждого кадра передается как привязка в src.

то в вашем внутреннем html вы можете получить доступ к идентификатору фрейма, в который он загружен, через location.hash:

<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>

тогда вы можете получить доступ к parent.document.getElementById (), чтобы получить доступ к тегу iframe изнутри iframe

person Mark Porter    schedule 01.06.2009
comment
Да, это было бы наиболее логичным решением, но иногда мне нужно изменить src iframe .. и передача этого хэша или параметра GET для каждого запроса не годится .. - person José Leal; 01.06.2009
comment
почему каждый раз передавать хеш - это плохо? Он виден только браузеру, а не серверу, и не влияет на кеширование, как параметр get. - person Mark Porter; 01.06.2009