Hide iframes if not correctly loaded - javascript

I have several iframes pointing to external websites on my page. In case those services are interrupted or changed, I would like to hide those iframes instead of displaying an error message on my page.
Is there any way to find out in Javascript if the iframe has been loaded correctly?
I added a class to hide the iframe and then remove it with jQuery when the iframe is ready, like this:
$('#widget').ready(function () {
$('#widget').removeClass('hidden');
});
It still removes the hidden class when I put an invalid URL in the iframe src, showing the error iframe.
My questions are two:
How can I make the function just run if the iframe has been loaded correctly?
Instead of using $('#widget').ready, I would like to use $('iframe').ready to target all iframes at once; if I do so, how to refer to the specific iframe loaded, inside the function?
Thanks!

Your question can be boiled down to :
how can I check if an URL exists and the website is alive from Javascript ?
The answer is splitted in:
For internal URLs, use AJAX and check the response code: if it's 2xx or 3xx (eg 200 or 302), it's fine. If it's 4xx or 5xx (eg. 404 or 500) it's bad. Read more on a similar answer.
For external URLs, you can't do it due to a security measure called same-origin policy.
Since it seems you are pointing to external URLs, here is my suggestion:
Create a server-side component (a Servlet, a RESTful WebService, a Struts2 action, etc... whatever you prefer, according to the server side technology you are using) that perform the check for you, and return a streamed response with the data (if any) and the HTTP response code that you can check for errors. Then from the <iframe>s call your component URL.

You probably can't do exactly what you want using Javascript, you need server-side things, PHP for instance.
However, here are some helpful places to look for more info:
You can run code after an iframe loads with this JQuery function:
$('#myIframe').load(function(){
//your code (will be called once iframe is done loading)
});
Look at this Stack Overflow question and answers about iframe loading.
To target the specific element inside the function, do:
$('iframe').aFunction(function() { this.doSomething(); } );
Look at this Stack Overflow question and answers about "this".

Related

Autoloading invalid javascript files

I've created a script which autoloads javascript files based on the users location. Like any other loaders, I create a <script> element, set it's src attribute and add it to <head>. I then listen for onload and onreadystatechanged etc. events, then check for the presence of a value exposed by the file. This works.
The problem is, when supplied with an invalid cross origin url "http://fail_on_purpose", my ISP returns HTML (directing the browser to reload with a different address). I can catch this in the onload event, but it's too late. The HTML has already been injected on the page within the <script> tags. This then causes the browser (firefox at least) to issue a SyntaxError exception.
All I can do is remove the offending element from the DOM. But, I don't know if this is going to cause problems in other browsers, so I would prefer to not have the error at all.
What is the best way to check for a valid javascript file then inject it into the page?
Update:
Issuing a HEAD or GET request to check if the file exists/is valid, doesn't work due to the "Cross Origin" protection in the browser. I don't have access to the CDN, so that is an unfixable problem.
You could send a HEAD request and parse response headers to see if the page returns successfully, i.e. not with redirection, client error or server error response code. Any decently implemented server should set correct response code.
Ideally, you'd also check content-type to include application/javascript, if the server is set up to set it correctly.
If this matches, you know that the script exists, so you can then proceed with loading it the same as you do now.
Alternatively, you already get these headers with GET request, so you could do all that with a single request. But with incorrect request, you'll be waiting for all the payload before determining it's incorrect, which will take up more time and waste data transfer. The latter is something worth considering if you're expecting mobile users, you wouldn't want to waste data plans like that.
As Sumit suggests, you might load the script via an Ajax request, then check it somehow (e.g. because you know that it contains a particular string).
On success, just proceed as you did - append a <script> tag to the head or body element with the "src" attribute set. If caching is enabled for the URL, the browser won't do another HTTP request for that.
Using the Ajax-loaded JS code directly (by setting scriptElem.text instead of the "src" attribute) is another option, but not as good, since it is subject to CORS restrictions. See jQuery's DOMEval function, https://code.jquery.com/jquery-3.1.0.js (line 77)
Since you want to load the code from the Google servers, the "src"-attribute version is better.

PHP HttpRequest to create a web page - how to handle long response times?

I am currently using javascript and XMLHttpRequest on a static html page to create a view of a record in Zotero. This works nicely except for one thing: The page html title.
I can of course also change the <title>...</title> tag, but if someone wants to post the view to for example facebook the static title on the web page will be shown there.
I can't think of any way to fix this with just a static page with javascript. I believe I need a dynamically created page from a server that does something similar to XMLHttpRequest.
For PHP there is HTTPRequest. Now to the problem. In the javascript version I can use asynchronous calls. With PHP I think I need synchronous calls. Is that something to worry about?
Is there perhaps some other way to handle this that I am not aware of?
UPDATE: It looks like those trying to answer are not at all familiar with Zotero. I should have been more clear. Zotero is a reference db located at http://zotero.org/. It has an API that can be used through XMLHttpRequest (which is what I said above).
Now I can not use that in my scenario which I described above. So I want to call the Zotero server from my server instead. (Through PHP or something else.)
(If you are not familiar with the concepts it might be hard to understand and answer the question. Of course.)
UPDATE 2: For those interested in how Facebook scraps an URL you post there, please test here: https://developers.facebook.com/tools/debug
As you can see by testing there no javascript is run.
Sorry, im not sure if i understand what you are trying to ask, are you just wanting to change the pages title?
Why not use javascript?
document.title = newTitle
Facebook expects the title (or opengraph :title tags) to be present when it fetches the page. It won't execyte any JavaScript for you to fill in the blanks.
A cool workaround would be to detect the Facebook scraper with PHP by parsing the User Agent string, and serving a version of the page with the information already filled in by PHP instead of JavaScript.
As far as I know, the Facebook scraper uses this header for User Agent: "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
You can check to see if part of that string is present in the header and load the page accordingly.
if (strpos($_SERVER['HTTP_USER_AGENT'], 'facebookexternalhit') !== false)
{
//synchronously load the title and opengraph tags here.
}
else
{
//load the page normally
}

HTML, Javascript: difference between an ajax call and changing the source of an iframe

Context: I'm trying to code a javascript function to like a certain post on tumblr, based on this link . I tried using an ajax call instead of changing the source of an iframe, but it doesn't work. Of course, changing the source of an iframe works.
So, what can be the difference that make this not work?
$baseUrl = 'http://tumblr.com/like/';
function LikePost( $postID, $reblogUrl )
{
/*
http://www.tumblr.com/<command>/<oauthId>?id=<postId>
<command>: like or unlike
<oauthId>: last eight characters of {ReblogURL}
<postId>: {PostID}
Exemple of Url
http://www.tumblr.com/like/fGKvAJgQ?id=16664837215
*/
$oauthId = $reblogUrl.substring( $reblogUrl.length - 8, $reblogUrl.length);
$likeUrl = $baseUrl + $oauthId + '?id=' + $postID;
$.ajax({
url: $likeUrl,
type:'POST'
});
}
AJAX requests are bound by same domain policy, with some exceptions that aren't worth listing since they don't work unless you control both domains.
In this case, you're calling a tumblr domain from your website, which you can't do through AJAX. However, iframes, script elements, and img elements can point to any domain, so if the like url isn't returning any content to you, you can use any of those means to record the like.
If you didn't want to use an iframe, the other method you could use would be to make a request to your server via AJAX, then proxy the request to tumblr. Your server can go to any url it wants.
However, the iframe approach is easiest. I suggest going that route since you already got it working. ;)
They are intended for different purposes. As jmort253 noted above, AJAX calls work only for the same domain, whereas Iframes may span different domains. But if you are interested in loading data from the same domain, AJAX may be a better option. Many times, while using IFrame, you will see a loading sign on the tab-bar of the page, showing that something inside it is loading (it's the IFrame page which is loading, not the entire page), which you don't want the user to see, because that is the point of AJAX, loading data seamlessly, giving the user the illusion that the data is coming almost simultaneously. With AJAX, you won't have these problems.
And even if you want to load data from different domains, while Javascript itself is not upto the task, you can use PHP to do the loading part, then use Javascript to fetch the data from there.

Access a cgi Script Via a JavaScript

I am trying to make a link where when it is clicked, it goes to the site it is supposed to, but it also runs a cgi script. I have found different examples, but I still don't fully understand it.
In essence, I have two questions:
Where can I host the script so I can access it?
How do I access it?
Where can I host the script so I can access it?
If you want to access it from JavaScript then it has to be on the same origin (i.e. hostname and port) as the page the JavaScript is running in.
How do I access it?
You can either forget JavaScript, have a regular link and then have the CGI perform a 302 redirect, or you can use Ajax.
Beware of timing issues. It is possible for the browser to go to the next URL before it gets around to making the Ajax request. A redirect would probably be a better approach.
<script>
function callYourCGI(){
var i = new Image();
i.src = "your-cgi-url?name=value&name2=value2";
}
</script>
<a href="the-next-document.html" onclick="callYourCGI()">
The Image object is part of the HTML DOM. It allows you to manipulate images in an HTML page. Read about it here: http://www.javascriptkit.com/jsref/image.shtml
The script is creating an image object and then assigning the URL of your CGI script to the SRC attribute. This makes the browser perform a get request for the content of the URL. In this case, you aren't going to display the image object, so the content returned by your CGI script need not be a real image. If can be, if you want, though. Either way, the side-effect is that your CGI script is called, with some parameters if desired. An advantage of this method is that it does not violate the same origin policy, since images are allowed to be loaded from anywhere.

AJAX: problem with redirect

This is the first time ever I'm using AJAX, and I want to do the following on an otherwise static page www.xyz.org/some_site.html:
Send a GET request to another url "www.xyz.org/testscript"
if response has either status code != 200 or content != 'ok': do nothing
else: include sth on the website (i.e. set style="display:block" on an element that previously had "display:none")
I've implemented that successfully using basic AJAX. But:
There is an Apache redirect installed pointing from www.xyz.org/testscript to subdomain.xyz.org/testscript, the URL where the actual testscript lives (as AJAX doesn't support cross-domain calls even to subdomains afaik).
When I call www.xyz.org/testscript I get a 302 status code, and the content says "The document has moved here: subdomain.xyz.org/testscript".
How can I grab the 'final' return value?
I guess/hope any AJAX expert can give me a one-liner to solve that ...
AJAX (or XMLHttpRequest to be acurate) won't be tricked by a redirect. To be able to get content from another domain you need to use a proxy on the server. The following is a simple PHP proxy:
if(strpos($_GET['q'], "http://") === 0){
echo file_get_contents($_GET['q']);
}
use it like this:
xhr.open(GET, "www.xyz.org/proxy.php?q=subdomain.xyz.org/testscript", true);
The answer is, according to the comments above:
It's not possible to achieve what I want to do, as AJAX can't be tricked into following a redirect.
EDIT: I tried to solve it by adding another javascript file at subdomain.xyz.org/another.js and throwing all AJAX code from my static html site into it.
Then, on the static html site, I included this script with an ordinary
<script src="subdomain.xyz.org/another.js">
tag. But that wouldn't work either ... cheated myself: Including the javascript on my static page results in the original problem again (cross-domain calls forbidden).

Categories

Resources