How to trigger onload event when downloading a file in an iframe? - iframe

Suppose we have the following HTML file:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test iframe download</title>
<script type="text/javascript">
var init = 0;
function download() {
document.getElementById("dload_frame").src = "http://example.com/dload.py";
}
function alert() {
if (init == 0) {
init = 1;
}
else {
document.getElementById("alert_span").innerHTML = "Got it!";
}
}
</script>
</head>
<body>
<span id="alert_span">Main content.</span><br/>
<input type="button" value="Download" id="btn" onclick="download()" />
<iframe id="dload_frame" src="http://404.com/404" onload="alert()"> </iframe>
</body>
</html>
Now, if the URL to which iframe's src is being rewritten to (in this case - "http://example.com/dload.py") returns HTML, no problem: the onload event fires, the span's contents are replaced, everybody's happy.
However, if the content type of the file returned by the URL is set to something that forces the browser to open the save file dialog, the iframe's onload event never fires.
Is there any workaround? Using iframes isn't necessary, the desired behavior is to launch a callback after the browser begins downloading the supplied file.

I have encountered the same problem as this:
Here is my work-around, please see if it works for you:
<script>
function download(){
var url = 'http://example.com/dload.py';
var htm = '<iframe src="' + url +'" onload="downloadComplete()"></iframe>';
document.getElementById('frameDiv').innerHTML = htm;
}
</script>
<div style="display:none" id="frameDiv">
</div>
<button onclick="download()">download file</button>
As far as I can remembered iframe's onload event fires only once.
Setting another value for src attribute will not cause the onload event to fire again.

I have the same problem, onLoad handler is only fire when the content change. If you download a file. If you delete HTTP header to print file content on iframe, the onload is correctly fire.

My solution after many different approaches to get this working across ff ie safari and chrome was not have a 2 step download.
the original JS request to create an iframe loads a src that would normally have loaded the pdf
However, the src now loads a page with yet another iframe inside of it, which now contains the url of the pdf.
in the html response I trigger the onload and also a catchall setTimeout funciton which calls my response on window.parent.window.handlerfunction which my onload on the top iframe would have been. The result is a PDF download and a trigger on the top level parent of the handler function that works across the browsers since it no longer relies on detecting an actual iframe load but rather relies on supported parent/child window relationships.
hope this helps someone who was also stuck

You can check iframe readyState property repeatedly after short time intervals until it gets completed.
function iframe_onload(iframe_id, js) {
var iframe = document.getElementById(iframe_id);
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
if (iframeDoc.readyState == 'complete') {
eval(js)
return;
}
window.setTimeout('iframe_onload("' + iframe_id + '",`' + js + '`);', 100);
}

You might need help of jquery for this, for instance you can do this:
$.get('http://example.com/dload.py',{},function(result){
$('alert_span').html(result);//or some content
});

Related

refresh iframe parent page using getElementById

Is is possible to refresh only once iframe parent page when iframe contain specified div id ?
I tried this on parent page but didn't work :
if document.frames('myiframe').(document.getElementById("iframedivID") !== null) { window.location.href = "mysite.com"; }
It is taking time to load the inner document. So we have to wait till inner document gets loaded and once it is loaded, the inner div can be accessed. Here is my example HTML and javascript code. Due to this, for the first time, you may get null in the alert. Hope this helps.
Test.html
<iframe id="iframedivID" src="Test1.html"></iframe>
Test1.html
<div id='myDiv'>My name is ravindra</div>
<script type="text/javascript">
if (window.parent.window.location.href.toString().indexOf("?refresh") == -1){
window.parent.window.location.href="Test.html?refresh";
}
</script>

Control one iFrame from another iFrame

This works …
Link text
but this doesn't …
<script type="text/javascript">
window.onload = function() {
var a = document.getElementById("mylink");
a.onclick = function() {
parent.document.getElementById('frameName').src = 'page.html';
}
}
</script>
<a id="mylink" href="page.html">LINK</a>
Any idea why I can't get the element by id from one iFrame to another? Also I know very little code so I apologize in advance if its obvious.
First i would make sure that the security of the site within the IFrame allows you to do this kind of stuff. Check out this link:
Overcoming "Display forbidden by X-Frame-Options"
Next, i would worry about the target of your anchor tag. With specifying it will default to self. In your second piece of code the target will be _self. Thus, when you click the link your javascript will want to change the source of the IFrame while the link will want to change the entire page. I would pick either a JS or HTML implemetation of linking and not both. Here is something that i put together to show one way of changing the iFrame without an actual anchor tag.
<html>
<body>
<iframe id="frameName" src="page.html"></iframe>
<button onclick="changeFrame()">LINK</button>
<script>
function changeFrame() {
document.getElementById('frameName').src ='page2.html';
}
</script>
</body>
</html>

IE alternative to window.stop() (cancel all pending requests)

I'm looking for an alternative to window.stop() for IE. I have tried document.execCommand('Stop'), but it doesn't seem to work. I'm trying to cancel a XMLHttpRequest which is called from within a ASP user control i'm using. I can't use jQuery's .abort() since i do not set the request my self.
I assume control on the page uses jQuery.ajax and you know when you need to abort the request, under your criteria.
How about something like this?
(function ($) {
var xhr = null,
originalAjax = $.ajax,
updatedAjax = function (url, options) {
xhr = originalAjax(url, options);
};
$.ajax = updatedAjax;
})(jQuery);
Now you have a variable called xhr which holds the underlying xmlhttp object. You can call abort() on the object when you need to.
The draw back is that variable will be populated for each ajax request done by jQuery, and I would only include this script on that particular page, maybe even reset the ajax when you are done.
I haven't tried this, just an idea, as I have been mocking ajax calls all the time. Some might think that this approach is a little bit drastic!
Hope you find it useful.
If you have access to the object you can do it with the object's abort() and onreadystatechange event handler. Here is a working example I tweaked from w3schools
<html>
<head>
<script type="text/javascript">
function loadXMLDoc()
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==2){ xmlhttp.abort();}
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","xmlhttp_info.txt",true);
xmlhttp.send();
}
</script>
</head>
<body>
<h2>Using the XMLHttpRequest object</h2>
<div id="myDiv"></div>
<button type="button" onclick="loadXMLDoc()">Change Content</button>
</body>
</html>
As you can see, the request text is not loaded because it gets aborted.
I understand you don't set the request yourself, but do you have any kind of access to it, so that you can use the onreadystatechanged-event in javascript? If so, you can then determine whether or not you have to cancel the event.

asp.net mvc JavaScript in View User Controls rendered through regular browser request and AJAX request

I have this code in some of my ASCX files:
<%=Html.ActionLink(Resources.Localize.Routes_WidgetsEdit, "Edit", "Widget",
new { contentType = Model.ContentType, widgetSlug = Model.Slug, modal=true},
new
{
rel = "shadowbox;height=600;width=700",
title = Resources.Localize.Routes_WidgetsEdit,
#class = "editWidget"
})%>
Take note of that rel="shadowbox..." there. This is to wire up ShadowBox Lightbox clone for this ActionLink.
This works fine when user requests a page containing this User Control thru normal browser request. But I also render/build those View User controls trough AJAX requests. For instance, I would make request to /Widget/RenderToString/... using jQuery .ajax() method and it would return HTML code for that control. This works fine and it renders the code fine. I would then insert (append) the result to a DIV in a page from where the AJAX request was made. This also works fine and the returned HTML gets appended. The only problem is - ShadowBox is not wired up. Even though the code for it gets rendered.
It seems it requires page reload (F5) every time to wire ShadowBox up. Since I am doing AJAX GET and instant append to get rid of having to make a server roundtrip, I would also want ShadowBox to wire up without doing refresh.
Can someone help me with that? Thank you
UPDATE:
Yes, I have this in my Site.Master head:
<script src="<%=Url.Content("~/Scripts/shadowbox-build-3.0rc1/shadowbox.js") %>" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
// insert functions calls here that provide some default behaviour
externalLinks();
});
Shadowbox.init({
language: "en",
players: ["img", "html", "iframe"],
onClose: function() { location.reload(true) }
});
</script>
How do I init the Shadowbox again after AJAX call?
There are many shadowbox plugins... which one are you using? (I can't give you exact code without it.) In any case I imagine you have something in your $(document).ready(function () { ... }); that tells shadowbox plungin to bind itself. You need to call that again after the AJAX call.
Just found the solution here
// call this after adding the new HTML to the page
// set up all anchor elements with a "editWidget" class to work with Shadowbox
Shadowbox.setup("a.editWidget", {});

Call onresize from ASP.NET content page

I have a JavaScript method that I need to run on one of my pages, in particular, the onresize event.
However, I don't see how I can set that event from my content page. I wish I could just put it on my master page, but I don't have the need for the method to be called on all pages that use that master page.
Any help would be appreciated.
Place the following in your content page:
<script type="text/javascript">
// here is a cross-browser compatible way of connecting
// handlers to events, in case you don't have one
function attachEventHandler(element, eventToHandle, eventHandler) {
if(element.attachEvent) {
element.attachEvent(eventToHandle, eventHandler);
} else if(element.addEventListener) {
element.addEventListener(eventToHandle.replace("on", ""), eventHandler, false);
} else {
element[eventToHandle] = eventHandler;
}
}
attachEventHandler(window, "onresize", function() {
// the code you want to run when the browser is resized
});
</script>
That code should give you the basic idea of what you need to do. Hopefully you are using a library that already has code to help you write up event handlers and such.
I had the same problem and have come across this post :
IE Resize Bug Revisited
The above code works but IE has a problem where the onresize is triggered when the body tag changes shape. This blog gives an alternate method which works well
How about use code like the following in your Content Page (C#)?
Page.ClientScript.RegisterStartupScript(this.GetType(), "resizeMyPage", "window.onresize=function(){ resizeMyPage();}", true);
Thus, you could have a resizeMyPage function defined somewhere in the Javascript and it would be run whenever the browser is resized!

Resources