Detect if the iframe content has loaded successfully - javascript

I have a widget that contains an iframe. The user can configure the url of this iframe, but if the url could not be loaded (it does not exists or the user does not have access to internet) then the iframe should failover to a default offline page.
The question is, how can I detect if the iframe could be loaded or not? I tried subscribing to the 'load' event, and, if this event is not fired after some time then I failover, but this only works in Firefox, since IE and Chrome fires the 'load' event when the "Page Not Found" is displayed.

I found the following link via Google: http://wordpressapi.com/2010/01/28/check-iframes-loaded-completely-browser/
Don't know if it solves the 'Page Not Found' issue.
<script type="javascript">
var iframe = document.createElement("iframe");
iframe.src = "http://www.your_iframe.com/";
if (navigator.userAgent.indexOf("MSIE") > -1 && !window.opera) {
iframe.onreadystatechange = function(){
if (iframe.readyState == "complete"){
alert("Iframe is now loaded.");
}
};
} else {
iframe.onload = function(){
alert("Iframe is now loaded.");
};
}
</script>
I haven't tried it myself, so I don't know if it works. Good luck!

Nowadays the browsers have a series of security limitations that keep you away from the content of an iframe (if it isn´t of your domain).
If you really need that functionality, you have to build a server page that have to work as a proxy, that receive the url as a parameter, test if it is a valid url, and does the redirect or display the error page.

If you control the content of the iframe, the iframe can send a message to the parent.
parent.postMessage('iframeIsDone', '*');
The parent callback listens for the message.
var attachFuncEvent = "message";
var attachFunc = window.addEventListener ;
if (! window.addEventListener) {
attachFunc = window.attachEvent;
attachFuncEvent = "onmessage";
}
attachFunc(attachFuncEvent, function(event) {
if (event.data == 'iframeIsDone') { // iframe is done callback here
}
});

How about checking if the url is available and only then setting the actual url of the iframe?
e.g. with JQuery
var url = "google.com"
var loading_url = "/empty.html"
document.getElementById("iframe").src = loading_url;
$.ajax({
url: url,
type: 'GET',
complete: function(e, xhr, settings){
if(e.status === 200){
document.getElementById("iframe").src = url;
}
}
});
Edit:
This does not seem to work cross domain, the status code is 0 in those cases.

If you have control over the contents of the iframe (e.g. you can add arbitrary code to the page), you can try to implement a special function in each of them, then in your page, you call that function and catch an error (via window.onerror handler) if the function called via eval fails because the page didn't load.
Here's example code: http://www.tek-tips.com/viewthread.cfm?qid=1114265&page=420

After the onload fires, you can scavenge the content of the iframe to see if it contains a usefull page or not. You'd have to make this browser specifuc unfortunately because they all display a different "page not found" message.
For more info, take a look here at http://roneiv.wordpress.com/2008/01/18/get-the-content-of-an-iframe-in-javascript-crossbrowser-solution-for-both-ie-and-firefox/

Related

How to avoid javascript `window.open` triggering popup window alert

I'm trying to build an off-site notification function in jQuery. The script first checks if the link is an external link and then checks against a db table entries for exceptions. If the link is external and not on the list of exceptions, send the visitor to a notification page. If it is an external link that's on the exception list, then open the link in a new window without the notification page.
I'm using a jQuery $.post call to send the link info out to a php script that retrieves the exceptions and returns a yes or no for if it needs to go to the notification screen. Here's the code:
$('a').click(function(){
var url =$(this).attr('href');
if(url !== '#'){
// ignore links that don't 'go' anywhere
if($(this).hasClass('alerted')){
// .alerted is used on the notification page to show the user's already been notified & prevents an infinite loop of notifications.
window.open(url);
return false;
}else if(url.substr(0,4) !='http'){
// check that the url isn't an internal link ('/page.php' for example)
return true;
}
// ajax script to check url is external and is there an exception. Returns as json object:
// link: link
// notify: true/false
$.post("/scripts/form_process.php", { action : 'offsite', link: url}, function(data){
if(data.notify == true){
// if visitors should be notified, redirect to the following link:
window.location= '/leaving-site?link='+encodeURIComponent(data.link);
return false;
}else{
// if the link is in the exception list, don't notify but do open the link in a new window:
window.open(data.link);
}
});
return false;
}
});
This is working fine except that so long as the window.open(url) command is inside the $.post success function, the browser is treating it like a popup instead of as a natural link. This seems to be a problem when using window.open inside the ajax call as far as I can tell. When I use it here:
if($(this).hasClass('alerted')){
// .alerted is used on the notification page to show the user's already been notified & prevents an infinite loop of notifications.
window.open(url);
return false;
}
I don't get the pop up blocker.
I can't hard code the exceptions list and I have to check every link - I can't assume a class will be added to the links that need to be notified for example.
How can I open the external link in a new tab and avoid the popup blocker in this code?
The classic way to solve this is as follows:
Create the new window before the AJAX call:
var newWindow = window.open('', '_blank');
And in the success - you assign the URL to the new window like so:
newWindow.location.href = 'http://example.com';
Full example with your code:
$('a').click(function(){
var url =$(this).attr('href');
if(url !== '#'){
// ignore links that don't 'go' anywhere
if($(this).hasClass('alerted')){
// .alerted is used on the notification page to show the user's already been notified & prevents an infinite loop of notifications.
window.location = url;
return false;
}else if(url.substr(0,4) !='http'){
// check that the url isn't an internal link ('/page.php' for example)
return true;
}
// ajax script to check url is external and is there an exception. Returns as json object:
// link: link
// notify: true/false
var newWindow = window.open('', '_blank');
$.post("/scripts/form_process.php", { action : 'offsite', link: url}, function(data){
if(data.notify == true){
// if visitors should be notified, redirect to the following link:
newWindow.location.href= '/leaving-site?link='+encodeURIComponent(data.link);
return false;
}else{
// if the link is in the exception list, don't notify but do open the link in a new window:
newWindow.location.href(data.link);
}
});
return false;
}
});

could not connect to extensions after I document.write my webpage

I found questions regarding "extension not able to connect in new tab",where the solution is to use chrome.tab module, but din't found anything like this:
I am stuck at this from many days, I will be glad if anyone could help me around.
I am using extensions for cross Domain calls, but my webpage can connect to the extension (I think content script) only when my page is a pure html page.If I change my page's content using:
document.open();
document.write(html);
document.close();
(I did this keep the url of my webpage same when a user log in)
I cannot get any Response from extension.
Is there any solution which I am missing.
code for Reference:
HTML where I replace page:
PageLoader.prototype.loadHTML = function(html) {
if (history.pushState)
try {window.history.pushState(null, null, document.URL);}
catch (e) {};
document.open();
document.write(html);
document.close();
};
crossDomain Code:
this is function which is called on click of some button
`window.addEventListener( "message", function(event) {
if (event.source != window ) return;
callback(event.data.text);
});
window.postMessage( { type: "com_logincat_xhr_get", url: url }, "*");
`
This postMessage is done but did not get any response from chrome extension's content_script.js (only If I have used document.write in my webpage to replace the content).
content_script.js also contain eventListner for message.
window.addEventListener( "message", function(event)
{
/* It contains piece of code to send message (chrome.runtime.sendmessage) */
};
I found at some places content_script.js attaches only at pageLoad and document.write might be replacing things, but I did not found any solution for this.
I think the code is correct as it works smoothly when page is a simple direct html.I don't know what wrong document.write do to my webpage
I Hope It will help,
Thanks for the help.
Hey this is my solution to the above problem.
I found that content_script.js of Extensions attaches to DOM only at pageLoad.
and using document.write('html')
I was modifying the DOM, which was creating Issue for the connection with content_script.js,
so I decided to use
document.documentElement.innerHTML = html;
using this I got into another problem which was that scripts were not getting executed which were in var html.
for that I did this:
var scriptToInclude = document.getElementsByTagName('script');
for (var n = 0; n < scriptToInclude.length; n++)
eval(scriptToInclude[n].innerHTML);
and it worked :)

Get response status code of cross domain iframe?

I have a iframe on my website which points to 3rd party page (i.e. Not on my domain and I don't have any control on their server).
I want to be able to just check if their website is being loaded properly inside the iframe or not. There can be cases where -
it gets blocked by some firewall
their service is down or something.
So that I can show a proper error message inside the iframe in that case. I was hoping that I can find out the iframe's response status code somehow. How can I achieve something like this?
Try this.
<script>
function checkIframeLoaded() {
// Get a handle to the iframe element
iframe = document.getElementById('your_iframe');
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
// Check if loading is complete
if ( iframeDoc.readyState == 'complete' ) {
iframe.contentWindow.onload = function(){
alert("I am loaded");
};
// The loading is complete, call the function we want executed once the iframe is loaded
afterLoading();
return;
}
// If we are here, it is not loaded. Set things up so we check the status again in 100 milliseconds
window.setTimeout('checkIframeLoaded();', 100);
}
function afterLoading(){
alert("I am here");
}
</script>
<body onload="checkIframeLoaded();">

Chrome Extension: How to get current webpage url from background.html

From my knowledge it is not possible directly by getting tab.url (only possible in the popup.html) and doing message passing also requires that popup.html be open. Is there anyway to bypass this and get the current page url from background.html?
My best shot was with message passing, which I used this code in background.html
var bg = chrome.extension.getPopupPage();
var myURL = bg.myURL;
then in popup.html I had:
chrome.tabs.getSelected(null, function(tab) {
var myURL = tab.url;
})
Anyways the above does't work at all. Anybody know of a way to do this without having to actually open up the popup?
chrome.tabs.query is supported from background pages, of course as long as you have the tabs permission. This is the supported route as of Chrome 19.
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
var tab = tabs[0];
var url = tab.url;
});
Note that currentWindow is needed because it would otherwise return the active tab for every window. This should be guaranteed to only return one tab.
Of course, keep in mind that this is an asynchronous API – you can’t access any data it provides except from within the callback function. You can store values (such as url here) at a higher scope so another function can access it, but that will still only provide the correct result after the callback is executed.
(The below is my original answer kept for posterity – this method is no longer necessary, requires an always-running background page, and getSelected() is deprecated.)
First put this in background.html and make the myURL variable global:
var myURL = "about:blank"; // A default url just in case below code doesn't work
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { // onUpdated should fire when the selected tab is changed or a link is clicked
chrome.tabs.getSelected(null, function(tab) {
myURL = tab.url;
});
});
Then run this in popup.html when you want to get the page url:
chrome.extension.getBackgroundPage().myURL;
So if I were to make that appear inside the popup and I went to Google and clicked your page or browser action, I'll see http://google.com/webhp in the popup.
Upon seeing this post I felt that there should be a way to mark a discussion as "obsolete".
Reasons being...
This question needs to migrate to manifest v2 and...
The answers both are not working. I am using a select onchange and posting the current tab's url which is not working.
Might be these all worked in manifest v1.
My answer is ...
var myURL = "not set yet";
window.addEventListener('load', function () {
chrome.tabs.getSelected(null,function(tab){
myURL=tab.url;
});
This is a little more work but works like a charm...
I would use a content script; it's relatively simple & allows you to get any info from current page you might want. Have the background page "inject" the script into the current webpage to gather the info you need. The script then just passes it back to the background.
background.js:
// Icon is clicked and triggers content script to be injected into current webpage
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: 'inject.js' });
});
// Listens for message back from content script and then runs
chrome.runtime.onMessage.addListener(function (request) {
var URL = request.url;
});
inject.js (content script):
// Gathers up in the information that you need from webpage
var pageInfo = {
"url": window.location.href
};
// Sends the information back to background.js
chrome.runtime.sendMessage(pageInfo);
Hope this helps someone!
chrome.tabs.getSelected(null, function(tab) {
var myURL = tab.url;
});
I don not understand, the code above can be used in background page to get the current tab's url.

IE6 does not parse the loaded JavaScript file (Recaptcha hosted by Google)

This is a really strange issue, I am trying to use the Recaptcha on one of the website, and it works for all browsers tested except for IE6.
I have made a reference to the google's js:
http://www.google.com/recaptcha/api/challenge?k=the_key
and it is loaded according to fiddler2 & the 'onreadystatechange' event (which have a readystate == 'loaded')
The normal work flow should be the loaded JS been parsed, and another js been requested, then the image loaded from google. my problem is that the first loaded JS file (content similar to below):
var RecaptchaState = {
site : 'xxxxxxxxxxxx',
challenge : 'xxxxxxxxxxxxxxxxxxxxxxxxx',
is_incorrect : false,
programming_error : '',
error_message : '',
server : 'http://www.google.com/recaptcha/api/',
timeout : 18000
};
document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
is not parsed. First, the following JS test:
typeof RecaptchaState == 'undefined'
Secondly, there is no second script request (according to fiddler2), not to say the recaptcha image...
The script tag is put inside the body, after the recaptcha markups, and I have even tried to load the JS dynamically:
function GetJavaScript(url, callback) {
var script = document.createElement('script');
script.src = url;
var head = document.getElementsByTagName('head')[0];
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function () {
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
done = true;
callback();
// remove the hanlder
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};
head.appendChild(script);
}
which gives same behaviour... what confuses me most is:
this issue occurs occasionally only when the page is redirectly from another page. (open the url directly in new browser window or refresh the page always works fine, however refresh page using JavaScript does not work...)
Please help, any advice and/or idea would be appreciated...
Double check that your script's src in the page source isn't api.recaptcha.net (some libraries use that, I know the Java one I was using did). If it is, that gets forwarded to www.google.com/recaptcha/api, and that seems to cause issues with IE6. Once I switched to using www.google.com/recaptcha/api as the actual script src, IE6 was completely happy. Good luck!
I solved this problem by using the https call, as per this thread in reCaptcha's Google Group.
This is not a solve, just an workaround.
Request the first js file: http://www.google.com/recaptcha/api/challenge?k=the_key
on the server site, and inject the first part of the script on the page directly:
var RecaptchaState = {
site : 'xxxxxxxxxxxx',
challenge : 'xxxxxxxxxxxxxxxxxxxxxxxxx',
is_incorrect : false,
programming_error : '',
error_message : '',
server : 'http://www.google.com/recaptcha/api/',
timeout : 18000
};
Then, using the GetJavaScript function and/or JQuery.getScript() function to load the second script:
http://www.google.com/recaptcha/api/js/recaptcha.js
This solution works for IE6 based on my test, and to make the server less load, I detect the user's browser at server end as well as client end to inject different logic.
I know this is dirty workaround, just in case this might help someone.
NOT ANSWER (or is it?):fo_Ok ie6. Seriously, forget it. Without this attitude ie6 will live forever. It is like ancient evil spirit which will be alive until someone believe in it.

Categories