Detect when an iframe starts to load new URL

JavascriptJqueryEventsIframe

Javascript Problem Overview


How can I detect that an iframe on my page starts to load a new page?

Our situation is:

  • When iFrame content starts to change we need to display a "loading" animation and hide the search-box.
  • I know how to handle the "iframe has finished to load" event (to hide the animation) but not how to catch the initial "starting to change" event...

Note: I can attach jquery "click" hook to the links on the menu, which will work. However, inside the iframe content there are many cross-reference links, and the "change" event also applies for them! So we need to catch event when user clicks on a link inside the iframe or when the iframe src is changed via javascript - because we also want to show the loading-animation and hide the search-box.

Javascript Solutions


Solution 1 - Javascript

I found a better solution if iframe and the container page is same origin, don't have to put extra code into the inner page:

<iframe src="same-origin.com" onload="content_finished_loading(this)"></iframe>
<script>
    var indicator = document.querySelector('.loading-indicator');
    var content_start_loading = function() {
        indicator.style.display = 'block';
    };

	var content_finished_loading = function(iframe) {
		indicator.style.display = 'none';
		// inject the start loading handler when content finished loading
        iframe.contentWindow.onunload = content_start_loading;
	};
</script>

Solution 2 - Javascript

I came up with following solution - which is only possible because we control the content of the iframe content and the host-window

Inside the iframe we add following script to the page footer (all pages use the same template, so this is a change to a single file)

<script>
window.onunload = function() {
	// Notify top window of the unload event
	window.top.postMessage('iframe_change', '*');
};
</script>

Inside the host-window we add this script to monitor the iframe state

function init_content_monitor() {
	var content = jQuery('.iframe');

	// The user did navigate away from the currently displayed iframe page. Show an animation
	var content_start_loading = function() {
		alert ('NOW: show the animation');
	}

	// the iframe is done loading a new page. Hide the animation again
	var content_finished_loading = function() {
		alert ('DONE: hide the animation');
	}

	// Listen to messages sent from the content iframe
	var receiveMessage = function receiveMessage(e){
		var url = window.location.href,
			url_parts = url.split("/"),
			allowed = url_parts[0] + "//" + url_parts[2];

		// Only react to messages from same domain as current document
		if (e.origin !== allowed) return;
		// Handle the message
		switch (e.data) {
			case 'iframe_change': content_start_loading(); break;
		}
	};
	window.addEventListener("message", receiveMessage, false);

	// This will be triggered when the iframe is completely loaded
	content.on('load', content_finished_loading);
}

Solution 3 - Javascript

There is already a possible solution at: https://stackoverflow.com/questions/2429045/iframe-src-change-event-detection

However, if you want to manipulate the target page, then it is not needed to touch the iframe-target file content. Just add the correct JS code in parent page and it can access SAME-ORIGIN iframe. I used something like this:

<iframe id="xyz" ....>
.....
<script>
var iframeElement = document.getElementById("xyz");
var iframe_El = iframeElement.contentDocument || iframeElement.contentWindow.document;
// manipulate iframe_El wih "on complete" events and like that.
....
</script>

more at: https://jsfiddle.net/Lnb1stc8/

Solution 4 - Javascript

When you are creating the iframe dynamically, include the ONLOAD event like so...

F=document.createElement('iframe');
F.onload=function(){
    UpdateDetails(
        this.contentWindow.document.title,
        this.contentWindow.location
    );
};
F.src='some url';
document.getElementById('Some_Container').appendChild(F);

The onload event will now constantly update the global variables below via the function below, as the user surfs the net:

var The_Latest_Title='';
var The_Latest_URL='';
function UpdateDetails(Title,URL){
    The_Latest_Title=Title;
    The_Latest_URL=URL;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPhilippView Question on Stackoverflow
Solution 1 - JavascriptBruceView Answer on Stackoverflow
Solution 2 - JavascriptPhilippView Answer on Stackoverflow
Solution 3 - JavascriptT.ToduaView Answer on Stackoverflow
Solution 4 - Javascriptuser6242961View Answer on Stackoverflow