iFrame src 변경 이벤트 감지?


181

iframe의 내용을 제어 할 수 없다고 가정하면 부모 페이지를 통해 내용의 src 변경을 감지 할 수있는 방법이 있습니까? 어떤 종류의 부하가 있습니까?

내 마지막 수단은 iframe src가 이전과 동일하다면 1 초 간격 테스트를 수행하는 것이지만이 해키 솔루션을 사용하면 짜증이납니다.

도움이된다면 jQuery 라이브러리를 사용하고 있습니다.


3
의지 srciframe이의 링크를 클릭 할 때 속성 변경은? 잘 모르겠습니다. 추측해야한다면 "아니오"라고 대답하면됩니다. 속성을 모니터링 하는 방법 이 있지만 (Firefox에서는 AFAIK 이상)이 경우 어떤 속성을 사용할지 잘 모르겠습니다.
Pekka

이런 식으로 구현하려고하는데 srcDOM 의 속성 이 최신 버전의 FireFox 또는 Safari에서 변경 되지 않음을 확인할 수 있습니다 . 아래 @Michiel의 대답은 내가 지금까지 얻을 수 있었던 것만 큼 좋습니다.
Kaelin Colclasure

답변:


201

onLoad다음 예제와 같이 이벤트 를 사용할 수 있습니다 .

<iframe src="http://www.google.com/" onLoad="alert('Test');"></iframe>

iframe 내의 위치가 변경 될 때마다 알림이 팝업됩니다. 모든 최신 브라우저에서 작동하지만 IE5 및 초기 Opera와 같은 매우 오래된 브라우저에서는 작동하지 않을 수 있습니다. ( 소스 )

iframe에 상위 도메인과 동일한 도메인 내에 페이지가 표시contentWindow.location 되면 다음 예제 와 같이로 위치에 액세스 할 수 있습니다 .

<iframe src="/test.html" onLoad="alert(this.contentWindow.location);"></iframe>

13
당신은 this.contentWindow.location.href
Nikolai

@Daniel Vassallo는 보안 문제를 처리하려고 할 때이 접근 방식을 취한다고 가정하고 누군가가 onLoad 이벤트를 재정의 한 다음 iframe 컨텐츠를 변경할 수 없습니까?
Noam Shaish

15
this.contentWindow.location.href내가 얻을 때Permission denied to access property 'href'
Mazatec

4
this.contentWindow.location.href는 크로스 원점 요청을 수행하는 bcoz에서 작동하지 않습니다. :( 현재 모든 브라우저에서이를 제한합니다.
Naveen

2
수정 : this.contentWindow.location다른 도메인에서 사용할 수 있습니다. this.contentWindow.location.href다른 도메인 에서도 사용할 수 있지만 쓰기 전용입니다. 그러나 읽기 this.contentWindow.location.href는 동일한 도메인으로 제한됩니다.
wadim

57

JQuery <3 기반 답변

$('#iframeid').load(function(){
    alert('frame has (re)loaded');
});

하위 쿼리에서 언급했듯이 JQuery 3.0에서 다음과 같이 변경해야합니다.

$('#iframe').on('load', function() {
    alert('frame has (re)loaded ');
});

https://jquery.com/upgrade-guide/3.0/#breaking-change-load-unload-and-error-removed


3
계획 한대로 작동하지 않습니다. 초기 페이지로드시 경고를 발생시킵니다. 이 코드에 대한 계획에 따라 (제출을 위해 양식 제출 페이지의 대화 상자에 애니메이션을 적용하고 있습니다)이 솔루션은 작동하지 않습니다.
stacigh

@stracigh, 맞습니다. 이벤트는 프레임이로드 될 때마다 시작되므로 초기 페이지로드시 처음으로 발생합니다. 코드를 처음 트리거하지 않으려면 이것이 첫 번째 프레임로드 및 리턴임을 감지해야합니다.
Michiel

@FooBar, 예, 크로스 도메인에서 작동합니다. 사실 그것은 내가 사용한 것입니다. 그러나 해당 페이지가 다른 도메인에 있으면 iFrame의 페이지에 자바 스크립트를 사용할 수 없습니다.
Michiel

이것은 작동하고 내용이로드 될 때를 감지합니다 .src가 변경되는 시점을 감지하는 방법이 필요합니다. beforeLoad (로더를 활성화시키기 위해)와 같은 것
Andrea_86

@stacigh로 표시된 것처럼 상위 페이지로드에서 이벤트를 한 번 발생시킵니다. 해당 함수 외부에서 카운터를 선언하고 내부에서 읽으면 그 후에 변경 사항을 감지 할 수 있습니다. onload 핸들러 내부의 카운터를 증가 if (counter > 1) { // do something on iframe actual change }시키고 플러스는 시작시 카운터가 0으로 설정되었다고 가정 함
Alex

38

페이지를 제어 할 수 없으며 어떤 종류의 변화를보고 싶다면 현대적인 방법을 사용하십시오 MutationObserver

사용의 예, src속성이 바뀌는 것을 관찰iframe

new MutationObserver(function(mutations) {
  mutations.some(function(mutation) {
    if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
      console.log(mutation);
      console.log('Old src: ', mutation.oldValue);
      console.log('New src: ', mutation.target.src);
      return true;
    }

    return false;
  });
}).observe(document.body, {
  attributes: true,
  attributeFilter: ['src'],
  attributeOldValue: true,
  characterData: false,
  characterDataOldValue: false,
  childList: false,
  subtree: true
});

setTimeout(function() {
  document.getElementsByTagName('iframe')[0].src = 'http://jsfiddle.net/';
}, 3000);
<iframe src="http://www.google.com"></iframe>

3 초 후 출력

MutationRecord {oldValue: "http://www.google.com", attributeNamespace: null, attributeName: "src", nextSibling: null, previousSibling: null…}
Old src:  http://www.google.com
New src:  http://jsfiddle.net/ 

jsFiddle

원래 질문이 이것으로 복제되어 여기에 게시 된 답변입니다.


웹 구성 요소를 사용하고 있고 사용자 지정 구성 요소 중 하나에 src 특성이 있으면 어떻게합니까? 나는 이것이 실수로 그것을 가져올 것이라고 생각합니다.
Luke

그런 다음의 옵션을 변경하십시오 observe. 이것은 단지 예일뿐입니다.
Xotic750

@PaulRoub는 jsfiddle 링크를 제거하고 (복사 / 붙여 넣기 오류 여야 함) 코드를 스 니펫으로 포함했습니다.
Xotic750

4
그러나 필자의 경우 frame.contentDocument.URL은 src가 아닌 (프레임 내부의 링크에서) 변경됩니다. 내가 볼 수 있습니까?
httpete

확실하지 않다, 내가 생각하는 질문을 작성하는 것이 가장 좋습니다.
Xotic750

11

참고 : 스 니펫은 iframe의 원점이 동일한 경우에만 작동합니다.

다른 답변은 load이벤트를 제안 했지만 iframe의 새 페이지가로드 된 후에 발생 합니다. 새 페이지가로드 된 후가 아니라 URL이 변경된 직후에 알림을 받아야 할 수도 있습니다 .

다음은 일반적인 JavaScript 솔루션입니다.

function iframeURLChange(iframe, callback) {
    var unloadHandler = function () {
        // Timeout needed because the URL changes immediately after
        // the `unload` event is dispatched.
        setTimeout(function () {
            callback(iframe.contentWindow.location.href);
        }, 0);
    };

    function attachUnload() {
        // Remove the unloadHandler in case it was already attached.
        // Otherwise, the change will be dispatched twice.
        iframe.contentWindow.removeEventListener("unload", unloadHandler);
        iframe.contentWindow.addEventListener("unload", unloadHandler);
    }

    iframe.addEventListener("load", attachUnload);
    attachUnload();
}

iframeURLChange(document.getElementById("mainframe"), function (newURL) {
    console.log("URL changed:", newURL);
});
<iframe id="mainframe" src=""></iframe>

이는 srciframe 자체에서 작성된 URL 변경뿐만 아니라 속성 변경 을 성공적으로 추적합니다 .

모든 최신 브라우저에서 테스트되었습니다.

나는 이 코드로 요점 을 만들었다 . 다른 답변 도 확인할 수 있습니다 . 이것이 어떻게 작동하는지에 대해 심층적으로 설명합니다.


6

iframe은 항상 상위 페이지를 유지하므로이 페이지를 사용하여 iframe에있는 페이지를 감지해야합니다.

HTML 코드 :

<iframe id="iframe" frameborder="0" scrolling="no" onload="resizeIframe(this)" width="100%" src="www.google.com"></iframe>

JS :

    function resizeIframe(obj) {
        alert(obj.contentWindow.location.pathname);
    }

2

Jquery 버전 3.0부터 오류가 발생할 수 있습니다

TypeError : url.indexOf는 함수가 아닙니다

함으로써 쉽게 고칠 수있는

$('#iframe').on('load', function() {
    alert('frame has (re)loaded ');
});

1

다음은 Commerce SagePayCommerce Paypoint Drupal 모듈에서 기본적으로 document.location.href자체 iframe을로드 한 후 외부 iframe을로드하여 이전 값과 비교 하는 방법입니다.

따라서 기본적으로 아이디어는 빈 페이지를 자체 JS 코드와 숨겨진 형식의 자리 표시 자로로드하는 것입니다. 그런 다음 부모 JS 코드는 숨겨진 #actioniform이 외부 iframe을 가리키는 곳에 제출합니다 . 리디렉션 / 제출이 발생하면 해당 페이지에서 여전히 실행중인 JS 코드가 document.location.href값 변경을 추적 할 수 있습니다 .

다음은 iframe에서 사용되는 JS 예입니다.

;(function($) {
  Drupal.behaviors.commercePayPointIFrame = {
    attach: function (context, settings) {
      if (top.location != location) {
        $('html').hide();
        top.location.href = document.location.href;
      }
    }
  }
})(jQuery);

그리고 부모 페이지에서 사용되는 JS는 다음과 같습니다.

;(function($) {
  /**
   * Automatically submit the hidden form that points to the iframe.
   */
  Drupal.behaviors.commercePayPoint = {
    attach: function (context, settings) {
      $('div.payment-redirect-form form', context).submit();
      $('div.payment-redirect-form #edit-submit', context).hide();
      $('div.payment-redirect-form .checkout-help', context).hide();
    }
  }
})(jQuery);

그런 다음 임시 빈 방문 페이지에 외부 페이지로 리디렉션되는 양식을 포함해야합니다.


이것은 해킹 일 수 있지만 오버 헤드는 돌연변이 관찰자보다 상당히 적습니다. 단일 페이지 응용 프로그램에서 사용될 때이 핵에서 남은 음식물이 가비지 수집되지 않도록하는 참조를 만들지 않도록주의하십시오.
Jeff
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.