Виклик функції батьківського вікна з iframe


282

Я хочу викликати функцію JavaScript батьківського вікна з iframe.

<script>
    function abc()
    {
        alert("sss");
    }
</script>

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>

1
Я не можу нічого показати зараз (2016), не знаю, чи підтримала б
старіша бауер

Відповіді:


438
<a onclick="parent.abc();" href="#" >Call Me </a>

Дивіться window.parent

Повертає посилання на батьківський код поточного вікна або підкадру.

Якщо у вікна немає батьківського, його батьківське властивість є посиланням на себе.

Коли вікно завантажено в <iframe>, <object>або <frame>його батько вікно з елементом вкладення в вікні.


17
Завжди враховуйте, що батьківський документ та документ iframe повинні збігатися за протоколом та доменним іменем. Якщо цього не сталося, ви отримаєте помилку безпеки, оскільки заборонено мати сценарій міждоменного сценарію.
a4bike

Мені просто цікаво, до якого alertз них буде викликано два ; батьківська alertфункція або функція iframe alert, якщо parent.abc();виклик iframe?
Прахар Мішра

@PrakharMishra Не плутайся. батьківський означає батьківський.
Саху V Кумар

3
@ a4bike для таких сценаріїв window.postMessage()(або window.parent.postMessage()) існує. Перевірте відповідь @Andrii
Fr0zenFyr

81

Нещодавно мені довелося з’ясувати, чому це теж не працює.

Javascript, який ви хочете зателефонувати від дитини, якщо кадр повинен бути в голові батьків. Якщо він знаходиться в тілі, сценарій недоступний у глобальному масштабі.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="parent.abc();" href="#">Click Me</a>
    </iframe>
</body>

Сподіваюсь, це допоможе тому, хто знову натрапить на це питання.


1
Жодна з методик, згаданих у цій публікації, не працює в Chrome. Будь-які рішення для цього?
Кумар Куш

3
Якщо я правильно пам’ятаю, я не міг змусити це працювати так, як очікувалося, якщо в iframe був інший домен для батьків. Вибачте, це не рішення, але це може пояснити, чому це не працює.
Еш Кларк

1
Так. Я знаю, що це через різні домени, але чи не існує способу вирішити це?
Кумар Куш

1
Я щойно опублікував, що може бути вирішенням вашої проблеми. Подивіться на іншу відповідь.
Еш Кларк

1
Відповідно до тих самих правил визначення політики походження (див. En.wikipedia.org/wiki/… ), субдомени вважаються різними іменами хостів для субдомену домену. Якщо ви ще цього не зробили, ви можете спробувати просто встановити document.domain на піддомен?
Еш Кларк

73

Window.postMessage ()

Цей спосіб безпечно дозволяє cross-originспілкуватися.

І якщо у вас є доступ до батьківського коду сторінки, тоді можна викликати будь-який батьківський метод, а також будь-які дані можна передавати безпосередньо з Iframe. Ось невеликий приклад:

Батьківська сторінка:

if (window.addEventListener) {
    window.addEventListener("message", onMessage, false);        
} 
else if (window.attachEvent) {
    window.attachEvent("onmessage", onMessage, false);
}

function onMessage(event) {
    // Check sender origin to be trusted
    if (event.origin !== "http://example.com") return;

    var data = event.data;

    if (typeof(window[data.func]) == "function") {
        window[data.func].call(null, data.message);
    }
}

// Function to be called from iframe
function parentFunc(message) {
    alert(message);
}

Код iframe:

window.parent.postMessage({
    'func': 'parentFunc',
    'message': 'Message text from iframe.'
}, "*");
// Use target origin instead of *

ОНОВЛЕННЯ:

Примітка безпеки:

Завжди надайте конкретний targetOrigin, НЕ *, якщо ви знаєте, де повинен знаходитися документ іншого вікна. Якщо не надати конкретну ціль, розкриваються дані, які ви надсилаєте на будь-який зацікавлений шкідливий сайт (коментар ZalemCitizen ).

Список літератури:


1
Я вважаю за краще використовувати це над іншими. Тим більше, що має сенс використовувати iframes у документах з перехресним походженням (хоча програмісти використовують iframes частіше, ніж ні) та надаючи широку підтримку цієї функції у браузерах.
Fr0zenFyr

1
Дякую! Мені завжди доводиться витрачати годину або більше, повертаючись назад і досліджуючи, як робити обмін повідомленнями над складними, багатослівними прикладами. Це спрацювало за 60 секунд. Дякую за приклад, який є лаконічним і суттєвим.
RandallTo

2
варто підкреслити це (з веб-документів MDN ): Завжди надайте конкретний targetOrigin, а не *, якщо ви знаєте, де повинен знаходитися документ іншого вікна. Якщо не надати конкретну ціль, розкриваються дані, які ви надсилаєте на будь-який зацікавлений шкідливий сайт
ZalemCitizen

20

Я опублікував це як окрему відповідь, оскільки це не пов'язане з моєю наявною відповіддю.

Цю проблему нещодавно знову вирішили для доступу до батьків із iframe, що посилається на піддомен, та існуючі виправлення не спрацювали.

Цього разу відповідь полягала в тому, щоб змінити document.domain батьківської сторінки та iframe бути однаковим. Це введе в оману одні й ті ж перевірки політики походження на думку, що вони співіснують у абсолютно одному домені (субдомени вважаються різним хостом і не відповідають одній і тій же політиці перевірки походження).

Вставте наступне на <head>сторінку сторінки у рамці iframe, щоб вона відповідала батьківському домену (підкоригуйте для вашого типу).

<script>
    document.domain = "mydomain.com";
</script>

Зауважте, що це призведе до помилки при розробці localhost, тому використовуйте чек, як описано нижче, щоб уникнути помилки:

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 

а як бути з тестуванням цього в localhost? якісь шляхи для цього?
Умеш Авасті

Дивіться: "Зауважте, що це призведе до помилки при розробці локального хосту, тому використовуйте чек, як описано нижче, щоб уникнути помилки"
Еш Кларк

2
Варто зауважити, що (принаймні в Google Chrome) і батько, і дитина повинні ПОВИНЕНО встановити document.domain, навіть якщо один з них вже "правильний"! Приклад: Батько є example.comiframe є abc.example.com, тоді і батько, і iframe повинні зателефонуватиdocument.domain = "example.com"
KillerX

Так, це правильно, я зробив помилковий помилку: "сторінка у кадрі повинна бути однаковою". має бути "сторінка, а рамка рамки однакова". ..... Дякую!
Еш Кларк

для if (), чому б ви просто не використовували if (document.domain! = "mydomain.com"? Також я розгублений, чи не надходить <script> у батьківському вікні чи iFrame? Також, встановивши document.domain в iFrame генерує "Не вдалося встановити властивість" domain "на" Document ":" localhost "не є суфіксом" sc-localhost ".
користувач2568374

18

Можна використовувати

window.top

див. наступне.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="window.top.abc();" href="#">Click Me</a>
    </iframe>
</body>

При спробі викликати parent.custom_function (); з iframe не працює, ви можете знайти window.top.custom_function (); буду працювати. Працює для мене чомусь дивно. Усі мої javascripts у батьківському вікні вбудовані у колонтитул, і я десь прочитав, що включно з файлами JavaScript у нижньому колонтитулі викликає проблему parent.custom_function () не працює.
Фрізо Горстман

@Vinothkumar, одне питання, будь ласка, яка різниця між викликом "window.top.abc ()", ніж викликом лише "abc ()", заздалегідь дякую =)
Zilev av

@ Zilev av Весь пункт цього потоку викликає функцію в батьківському документі з дочірньої рамки. Ось і різниця. Виклик abc()працює, лише якщо вони function abc()були оголошені в iframe на відміну від батьківської сторінки. window.top.abc()проривається з рамки iframe у батьківський документ.
Шон Кендл

3

Ще одне доповнення для тих, хто цього потребує. Рішення Еша Кларка не працює, якщо вони використовують різні протоколи, тому будьте впевнені, що якщо ви використовуєте SSL, ваш iframe також використовує SSL, або він порушить функцію. Його рішення все-таки працювало для самих доменів, тому за це дякую.


2

Рішення, надане Еш Кларком для субдоменів, чудово працює, але зауважте, що вам потрібно включити document.domain = "mydomain.com"; як у заголовку сторінки iframe, так і на головній сторінці батьків, як зазначено у посиланні, перевіряється та сама політика походження

Важливим розширенням до тієї ж політики оригіналу, що застосовується для доступу до DOM JavaScript (але не для більшості інших ароматів перевірок того самого походження), є те, що два веб-сайти, що використовують спільний домен верхнього рівня, можуть вибрати комунікацію, незважаючи на те, що "той самий хост" перевірити, встановивши взаємно відповідне властивість document.domain DOM на той самий кваліфікований правий фрагмент їх поточного імені хоста. Наприклад, якщо http://en.example.com/ та http://fr.example.com/ обидва встановили document.domain на "example.com", вони з цього моменту вважатимуться однаковими для мета маніпуляції DOM.


Так, це правильно, я зробив помилковий помилку: "сторінка у кадрі повинна бути однаковою". має бути "сторінка, а рамка рамки однакова". ..... Дякую!
Еш Кларк

як щодо запуску файлів на локальному комп'ютері? яка цінність document.domain?
Раптор

Це буде localhostабо ip-адреса машини (зазвичай 127.0.0.1), залежно від того, що знаходиться в адресному рядку URL-адреси.
Еш Кларк

2

parent.abc () працюватиме на тому самому домені в цілях безпеки. Я спробував це вирішити, і моя працювала чудово.

<head>
    <script>
    function abc() {
        alert("sss");
    }

    // window of the iframe
    var innerWindow = document.getElementById('myFrame').contentWindow;
    innerWindow.abc= abc;

    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="abc();" href="#">Click Me</a>
    </iframe>
</body>

Сподіваюсь, це допомагає. :)


Це також справді лише будь-яке використання для документа iframe, додаючи величезних ускладнень, якщо вам потрібно посилатися на елементи управління на батьківській формі.
Павло

1

За допомогою Firefox та Chrome ви можете використовувати:

<a href="whatever" target="_parent" onclick="myfunction()">

Якщо моя функція присутня як в iframe, так і в батьківському, викличеться батьківський.


це не працює. Ось моя демонстрація: dotku.github.io/tech/html/iframe/iframe_function_container.html
Weijing Jay Lin

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

Прийнята відповідь не потребує того, щоб сценарій був у голові. Я не перевіряв, чи це рішення більше не потребує, щоб сценарій був у голові чи ні.
Хлопець Шалнат

0

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

Щоб цього уникнути, використовуйте схему модуля. У батьківському вікні:

var myThing = {
    var i = 0;
    myFunction : function () {
        // do something
    }
};

var newThing = Object.create(myThing);

Потім у iframe:

function myIframeFunction () {
    parent.myThing.myFunction();
    alert(parent.myThing.i);
};

Це схоже на зразки, описані в розділі "Наслідування" в насіннєвому тексті Крокфорда "Javascript: хороші частини". Ви також можете дізнатися більше на сторінці w3 про кращі практики Javascript. https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.