기본적으로, 나는 한 iframe
페이지에 포함하고는 iframe
몇 가지가 자바 스크립트 내가 부모 페이지에서 호출 할 필요가 루틴을.
이제는 전화해야하기 때문에 그 반대가 매우 간단 parent.functionName()
하지만 불행히도 나는 그 반대가 필요합니다.
내 문제는의 소스 URL 을 변경하는 것이 아니라에 iframe
정의 된 함수를 호출하는 것 iframe
입니다.
기본적으로, 나는 한 iframe
페이지에 포함하고는 iframe
몇 가지가 자바 스크립트 내가 부모 페이지에서 호출 할 필요가 루틴을.
이제는 전화해야하기 때문에 그 반대가 매우 간단 parent.functionName()
하지만 불행히도 나는 그 반대가 필요합니다.
내 문제는의 소스 URL 을 변경하는 것이 아니라에 iframe
정의 된 함수를 호출하는 것 iframe
입니다.
답변:
iFrame의 ID가 "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();
document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadget('verify_user');"
는 apache shindig 서버에 의해 프로그래밍 방식으로 생성되었지만 window.parent.document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadget('verify_user');"
작동합니다.
여기서 알아야 할 몇 가지 단점이 있습니다.
HTMLIFrameElement.contentWindow
아마도 더 쉬운 방법 일지 모르지만 표준 속성은 아니며 일부 브라우저는 대부분 오래된 브라우저를 지원하지 않습니다. DOM Level 1 HTML 표준은 window
객체 에 대해 아무 말도하지 않기 때문 입니다.
HTMLIFrameElement.contentDocument.defaultView
몇 가지 구형 브라우저는 허용하지만 IE는 허용하지 않는을 시도 할 수도 있습니다 . 그럼에도 불구하고 표준은 window
(1)과 같은 이유로 객체를 다시 가져 왔다고 명시 적으로 말하지 않지만, 관심이 있다면 여기에서 몇 가지 추가 브라우저 버전을 선택할 수 있습니다.
window.frames['name']
창을 반환하는 것이 가장 오래되고 가장 안정적인 인터페이스입니다. 그러나 name="..."
이름으로 프레임을 얻을 수 있으려면 속성 을 사용해야합니다 . 이는 약간 추한 / 더 이상 사용되지 않거나 / 전환 된 것입니다. ( id="..."
더 좋을 것이지만 IE는 그것을 좋아하지 않습니다.)
window.frames[number]
또한 매우 신뢰할 만하지 만 올바른 색인을 아는 것이 속임수입니다. 예를 들어이 문제를 해결할 수 있습니다. 페이지에 iframe이 하나만 있다는 것을 알고 있다면
자식 iframe이 아직로드되지 않았거나 액세스 할 수 없도록 잘못되었습니다. 통신 흐름을 반대로하는 것이 더 쉽다는 것을 알게 될 것입니다. 즉, 아이 iframe window.parent
이로드가 완료되고 다시 호출 될 준비가되면 스크립트에 알리도록합니다 . 자체 객체 중 하나 (예 : 콜백 함수)를 상위 스크립트에 전달하면 해당 상위는 연관된 HTMLIFrameElement에 대해 걱정할 필요없이 iframe의 스크립트와 직접 통신 할 수 있습니다.
methode()
부분을 주목하십시오 .
에서 부모 JS 함수를 호출 할 iframe
수 있지만 부모와 페이지에로드 된 페이지가 모두 iframe
같은 도메인 (예 : abc.com)에서 온 경우와 둘 다 동일한 프로토콜을 사용하는 경우에만 둘 다 on http://
또는 https://
입니다.
아래 언급 된 경우 통화가 실패합니다.
이 제한에 대한 해결 방법은 매우 안전하지 않습니다.
예를 들어 도메인 superwinningcontest.com을 등록하고 사람들의 이메일에 대한 링크를 보냈다고 상상해보십시오. 그들이 메인 페이지를로드 할 때 iframe
거기에 몇 가지를 숨기고 Facebook 피드를 읽거나 최근 Amazon 또는 PayPal 거래를 확인하거나 충분한 보안을 구현하지 않은 서비스를 사용하는 경우 돈을 송금 할 수 있습니다 계정. 이것이 JavaScript가 동일한 도메인 및 동일한 프로토콜로 제한되는 이유입니다.
IFRAME에서 함수를 창 객체에 공개하십시오.
window.myFunction = function(args) {
doStuff();
}
부모 페이지에서 액세스하려면 다음을 사용하십시오.
var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
onclick()
이벤트가 단순히 호출 하는 버튼이 포함되어 있습니다 window.print()
. 이것은 내용 을 iframe
완벽하게 인쇄합니다 . 그러나 iframe의 페이지의 공개 함수가 호출 window.print()
되고 상위 페이지가 공개 함수를 호출하면 상위의 컨텐츠가 인쇄됩니다. window.print()
공개 함수에서 호출 이 onclick
이벤트 에서와 같이 작동 하도록 어떻게 코딩해야 합니까?
onclick
. 에 전화하고 싶습니다 iframe.contentWindow.print()
.
document.getElementById('myFrame').contentWindow.print();' and the pubic function
호출하는 printContent ()`(oncick 이벤트 핸들러가 아님)는 다음과 같이 호출 window.print()
되었습니다.document.getElementById('myFrame').contentWindow.printContent();
iFrame의 대상과 포함하는 문서가 다른 도메인에있는 경우 이전에 게시 된 방법이 작동하지 않을 수 있지만 해결 방법이 있습니다.
예를 들어, 문서 A에 문서 B가 포함 된 iframe 요소가 있고 문서 A의 스크립트가 문서 B의 Window 객체에서 postMessage ()를 호출하면 해당 객체에서 메시지 이벤트가 시작되고 문서 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);
}
}
}
이 스크립트는 먼저 도메인이 예상 도메인인지 확인한 다음 사용자에게 표시하거나 메시지를 보낸 문서로 메시지를 다시 보내 메시지에 응답하는 메시지를 확인합니다.
Quirksmode는 이것에 대해 글을 올렸습니다 .
페이지가 이제 깨져서 archive.org를 통해서만 액세스 할 수 있으므로 여기에서 재현했습니다.
IFrames
이 페이지에서는 현재 페이지에서 iframe에 액세스하는 방법에 대한 간단한 개요를 제공합니다. 당연히 브라우저 고려 사항이 몇 가지 있습니다.
iframe은 인라인 프레임으로, 자체 URL이있는 완전히 별도의 페이지가 포함되어 있지만 다른 HTML 페이지 내에 배치되는 프레임입니다. 이것은 웹 디자인에서 매우 좋은 가능성을 제공합니다. 문제는 iframe에 액세스하는 것입니다. 예를 들어 iframe에 새 페이지를로드하는 것입니다. 이 페이지는 방법을 설명합니다.
프레임이나 대상?
근본적인 질문은 iframe이 프레임 또는 객체로 보이는지 여부입니다.
top.frames[1].frames[2]
. iframe이이 프레임 계층에 맞습니까?document.getElementById('theiframe'))
: 액세스)을 사용해야합니다. 일반적으로 브라우저는 '실제'(하드 코딩 된) iframe에 대한 두보기를 모두 허용하지만 생성 된 iframe은 프레임으로 액세스 할 수 없습니다.NAME 속성
가장 중요한 규칙은을 name
사용하더라도 속성 을 생성하는 모든 iframe을 제공 하는 것 id
입니다.
<iframe src="iframe_page1.html"
id="testiframe"
name="testiframe"></iframe>
대부분의 브라우저 name
는 iframe을 프레임 계층의 일부로 만들 려면 속성이 필요합니다 . 일부 브라우저 (특히 Mozilla) id
는 iframe을 객체로 액세스 할 수 있도록하기 위해를 필요 로합니다. iframe에 두 속성을 모두 지정하면 옵션을 계속 열어 둘 수 있습니다. 그러나 name
보다 훨씬 더 중요합니다 id
.
접속하다
iframe을 객체로 액세스하고 객체를 변경 src
하거나 iframe을 프레임으로 액세스하여 객체 를 변경합니다 location.href
.
document.getElementById ( 'iframe_id'). src = 'newpage.html'; frames [ 'iframe_name']. location.href = 'newpage.html'; 프레임 구문은 Opera 6이 지원하지만 객체 구문은 지원하지 않기 때문에 약간 선호됩니다.
iframe에 액세스
따라서 완벽한 크로스 브라우저 경험을 위해서는 iframe에 이름을 지정하고
frames['testiframe'].location.href
통사론. 내가 아는 한 항상 작동합니다.
문서에 액세스
name
속성 을 사용하면 iframe 내부의 문서에 액세스하는 것이 매우 간단 합니다. iframe에서 문서의 링크 수를 계산하려면을 수행하십시오
frames['testiframe'].document.links.length
.
생성 된 iframe
W3C DOM을 통해 iframe을 생성하면 iframe 이 즉시 frames
배열에 입력되지 않습니다 .frames['testiframe'].location.href
되지 않으며 구문이 즉시 작동하지 않습니다. 브라우저가 iframe이 배열에서 나타나기 전에 약간의 시간이 필요하며,이 시간 동안 스크립트가 실행될 수 없습니다.
document.getElementById('testiframe').src
모든 상황에서 구문 이 제대로 작동합니다.
target
링크 의 속성은 생성 된 iframe에 a name
와 a를 모두 제공했지만 Opera를 제외하고 생성 된 iframe에서 작동하지 않습니다 id
.
target
지원 이 없다는 것은 생성 된 iframe의 컨텐츠를 변경하기 위해 JavaScript를 사용해야한다는 것을 의미하지만, 어쨌든 JavaScript를 생성하기 위해서는 JavaScript가 필요하기 때문에 이것이 큰 문제가되지는 않습니다.
iframe의 텍스트 크기
호기심 많은 Explorer 6 전용 버그 :
보기 메뉴를 통해 텍스트 크기를 변경하면 iframe의 텍스트 크기가 올바르게 변경됩니다. 그러나이 브라우저는 원본 텍스트의 줄 바꿈을 변경하지 않으므로 텍스트의 일부가 보이지 않거나 줄 바꿈이 발생하는 동안 줄이 다른 단어를 가질 수 있습니다.
나는 매우 우아한 해결책을 찾았습니다.
당신이 말했듯이, 부모 문서에있는 코드를 실행하는 것은 상당히 쉽습니다. 그리고 그것은 내 코드의 기초입니다. 반대로하십시오.
내 iframe 이로 드되면 부모 문서에있는 함수를 호출하여 iframe의 문서에있는 로컬 함수에 대한 참조를 인수로 전달합니다. 부모 문서는 이제이 참조를 통해 iframe의 기능에 직접 액세스 할 수 있습니다.
예:
부모님 :
function tunnel(fn) {
fn();
}
iframe에서 :
var myFunction = function() {
alert("This work!");
}
parent.tunnel(myFunction);
iframe이로드되면 parent.tunnel (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');
var frame_win = getIframeWindow(el);
if (frame_win) {
frame_win.targetFunction();
...
}
...
같은 일이지만 조금 더 쉬운 방법은 iframe 내의 페이지에서 부모 페이지를 새로 고치는 방법입니다 . 부모 페이지의 함수를 호출하여 자바 스크립트 함수를 호출하여 페이지를 다시로드하십시오.
window.location.reload();
또는 iframe의 페이지에서 직접 수행하십시오.
window.parent.location.reload();
둘 다 작동합니다.