Як отримати доступ до батьківського iframe з JavaScript


170

Ну, у мене є IFrame, який називає ту саму сторінку домену. Моя проблема полягає в тому, що я хочу отримати доступ до деякої інформації з цього батьківського iframe з цієї названої сторінки (з JavaScript). Як я можу отримати доступ до цього iframe?

Докладніше: Є кілька таких кадрів, як цей, які можуть завантажувати ту саму сторінку, оскільки я програмую середовище Windows. Я маю намір закрити цей Іфрейм, тому мені потрібно знати, що мені слід закрити всередині нього. У мене є масив, що зберігає посилання на ці рамки.

РЕДАКТУВАННЯ: Там кадрів генеруються динамічно


навіть якщо рамки генеруються динамічно, ви можете призначити новий унікальний ідентифікатор, використовуючи якийсь лічильник, нарешті, вам не потрібно знати ідентифікатор, але ви можете легко шукати, дивіться мою відповідь.
Акаш Кава

Відповіді:


138

Також ви можете встановити ім'я та ідентифікатор на рівні значення

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

тож ви зможете використовувати наступний код всередині дочірньої сторінки

parent.document.getElementById(window.name);

16
Можливо, це не очевидно для всіх, але за допомогою цього методу ви можете отримати доступ до бібліотечного об’єкта батьків (лише якщо батько вже завантажив бібліотеку). Приклад: доступ до jQuery з батьком. $ ('#
Something

1
Це рішення сумісне з режимом динаміки сумісності IE5 +.
Slayner

Навіть у 2016 році це чудово працює як частина рішення проблеми друку IE iframeнадто малого. Але чому це працює? window.nameповертає рядок. Що відрізняється від використання, window.nameніж просто передавання імені id як рядка, який не працює.)?
Карл

3
Привіт, він не працює з Chrome 59 ..: VM111: 1 Uncaught DOMException: заблоковано кадр з початковим файлом " xxx " від доступу до кадру з перехресним походженням.
Didier68

Chrome бачить файли в тій самій папці, що і крос-походження, якщо не встановлено CORS. Кажуть, це для безпеки. Налаштування CORS потребує сервера. Надайте користувачам повідомлення про налаштування сервера чи зміну веб-переглядача, якщо виявлено Chrome.

90

Просто зателефонуйте 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;
}

2
Дякую! Працює на IE 6+, FF та Chrome!
rustyx

11
window.frameElementповертається, nullколи вікно та iframe мають різні домени, тобто перехресні повідомлення.
Qwerty

@Qwerty Ви знайшли рішення?
Аджай Патідар

@AjayPatidar Я думаю, що я здався. :(
Qwerty

78

Я рекомендую використовувати API postMessage .

У своєму кадрі iframe зателефонуйте:

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

На сторінці, на якій ви включаєте кадр, ви можете слухати такі події:

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

    }, false);

До речі, також можна здійснювати дзвінки в інші вікна, і не тільки в рамки кадрів.

Детальніше про API PostMessage читайте на блозі Джона Ресігса тут


7
Я думаю, що це, безумовно, найкраща відповідь, <iframe>вміст не повинен нічого знати про батьківську і навпаки. Вони повинні лише підкорятися простому договору про повідомлення. Дивовижно!
mfeineis

1
<iframe> все ще повинен знати домен батьків, правда?
Homr Zodyssey

1
@HomrZodyssey Батьківський домен доступний лише як механізм безпеки, якщо його невідомо, ви можете встановити '*'.
Амір Алі Акбарі

Використовувати '*'на клієнтах. Усі інші рішення дають помилку в браузері Chrome, який обробляє файли в папці клієнтів як такі, що не є "Оригінальним", оскільки сервер не налаштований Це найкраще і єдине рішення: dyn-web.com/tutorials/iframes/postmessage

30

Старе запитання, але у мене було саме це питання і я знайшов спосіб отримати кадр iframe. Це просто питання ітерації через масив батьківського вікна [] та тестування вмісту кожного вікна кадру проти вікна, в якому працює ваш код. Приклад:

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). Тож прокручування через них здається єдиним способом, якщо ви не хочете використовувати ідентифікатори.


1
Оновлення: це не спрацювало так, як рекламовано, і мені довелося використовувати contentWindow.document === документ. Не знаю, чому. Також у деяких браузерах я використовував contentDocument. Ну, мені це подобається!
Крістоф

1
Вибачте, правда, я протестував це лише у Firefox. :) Однак я мав успіх у використанні методу jQuery та contentWindow у кількох браузерах.
інгредієнт_15939

1
Оновлення: я дізнався, що ви також можете використовувати window.frameElement, але я не впевнений, які браузери його підтримують.
Крістоф

2
Я не думаю, що подібні речі більше не працюють; ви отримуєте помилку перехресного походження.
Ендрю Мао

@AndrewMao питання стосується одних і тих же документів про походження, тому немає жодних причин виникати проблем з поперечним походженням.
Крістоф

21

ви можете використовувати parentдля доступу до батьківської сторінки. Отже, для доступу до функції було б:

var obj = parent.getElementById('foo');

1
Кевін, проблема полягає в тому, щоб ЗНАТИ ідентифікатор. У мене є декілька іфреймів, і я хочу отримати доступ до них з коду всередині
Хосе Ліал

Все-таки отримуйте "Блокований кадр з початковим кодом" other-localhost: 8000 "від доступу до кадру з перехресним походженням."
користувач2568374

13

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

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

Добре працює в IE, Chrome та FF.


Здається, це заплутаний спосібvar iframe = frameElement
Оріол

frameElement повертає об'єкт у поточному контексті вікна, але parent.document.getElementById (frameElement.id) повертає об'єкт у контексті батьківського вікна, ви не можете запускати функції JavaScript JavaScript батьківського вікна з frameElement, спробуйте його у jsfiddle та дайте мені та приклад, якщо зможете .
Акаш Кава

6

Може просто використовувати

window.parent

у ваш iframe, щоб отримати кадр / вікна виклику. Якщо у вас було кілька кадрів виклику, ви можете використовувати

window.top

3

Спробуйте це, у своєму батьківському кадрі налаштуйте такі 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


Так, це було б найбільш логічним рішенням, але іноді мені потрібно змінити src iframe .. і передаючи цей параметр хешу чи GET, кожен запит не є корисним ..
Хосе Ліл

чому погано кожен раз передавати хеш? Він видимий лише для браузера, а не для сервера, і це не впливає на кешування, як би параметр get.
Марк Портер

-1
// just in case some one is searching for a solution
function get_parent_frame_dom_element(win)
{
    win = (win || window);
    var parentJQuery = window.parent.jQuery;
    var ifrms = parentJQuery("iframe.upload_iframe");
    for (var i = 0; i < ifrms.length; i++)
    {
        if (ifrms[i].contentDocument === win.document)
            return ifrms[i];
    }
    return null;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.