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 SagePay 및 Commerce 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.