JavaScript background work (wait until all processing finished and display result ) - javascript

i'm working in an application
i have to change some css files in the page and some images (reloading them from the server) using javascript , but it takes some time and it's obvious that page items are reloaded slowly -in slow connections- , so is it possible to do this processing in the background and then display the whole page when ready ??

AFAIU you can put it in a hidden IFRAME. In this IFRAME you handle onLoad event. However, this won't fasten up loading process, it will only hide it from user.
Examle:
Let's say that you have a long-lasting JavaScript method named longLoad() . You should put it in a separate HTML page named e.g. hidden.html.
<html>
<script type="text/javascript">
function longLoad() // javascript method here...
{
/// some code here...
}
</script>
<body onLoad="longLoad();">
</body>
</html>
Your main page (the one that is actually visible in browser) may look like this:
<html>
<body>
....
.... content
....
<iframe src ="hidden.html" width="100%" height="0">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
As you can see IFRAME height is set to 0 making it invisible on the page- that's why I called it hidden. However, when the user loads the page, the hidden IFRAME will be loaded too. And its onLoad event handler will also be called. And it is possible to access and modify content of the main page from that JavaScript event handler (through DOM trees).
PS. The above code was written from memory, however the presented solution works. It was used long before AJAX came into popularity.

You can hide the whole page while your work is going on, or you could load your CSS and images and only do the updates to the DOM when all your materials have made it to the client.
You can load an image by creating a new Image object:
var img = new Image();
img.onload = function() { /* do something */ };
img.src = "/new/image.png";
The "onload" function will run when the client has received the image file and it's ready to be displayed. Thus you could arrange to load up images that way, and use the "load" handlers to track when they're ready. When all of them are, then you can update the DOM and it should go very quickly.

Related

Ensuring that onLoad of an IFRAME doesn't execute too soon

I just discovered that the source of my issues is that the parent HTML makes calls to controls in a child IFRAME but is too quick about that and, sometimes, the super onLoad attempts to do so before the sub onLoad had a chance to add stuff to the DOM.
What can I do about it?
I've tried to set up some kind of feed-back from onLoad in the child. Failed miserably with so many strange errors that they can be summarized by dude, just please don't.
I've tried to set up a delayer, which is ugly of epic proportions and not 100% reliable.
EDIT:
In onload I do this:
var stuff = getReferenceToStuff();
var someDiv = stuff.contentWindow.document.getElementById("someDiv");
someDiv.className = "classy";
The problem is that sometimes the reference someDiv is null and sometimes (often when I reload the page by F5), it points to the correct element. I know it's because the contents of the IFRAME are a bit slower.
So my questions is this. How can I ensure that onload is postponed until the embedded IFRAME component's onload ensures that it's been loaded and all the components are there?
The onLoad event isn't always working correctly on document. It works correctly on each element though.
var iframes = document.getElementsByTagName('iframe'),
counter = 0,
max = iframes.length;
[].forEach.call(iframes, iLoaded);
function iLoaded() {
if (++counter === max) {
callback();
}
}
function callback() {
// All the iframes are loaded
}
When using window.onload all content of the body, including content of the iframes and all other resources like images, should be loaded before the onload is fired. However, some browsers have had problems with timing on firing onload, i.e. different browsers trigger the event in different stage of page parsing.
If you're using DOMContentLoaded or jQuery's $(document).ready(), only the HTML of the main page is loaded, but some resources are still under work (including iframe's content loading). I'm not aware what happens if you attach an inline listener for the iframe element itself.
If there's timing problems, maybe not trigger the function needing iframe reference in main window at all. Instead invoke that function in main window in irame's window.onload. But even this won't tackle the problem, if you're using some asynchronous technique to populate the iframe. In this case you need to invoke the function in main window after all requests have been completed.
(Now you maybe also know, what are the codesnippets I'd like to see in your post : ) ).
I have 2 solutions to your problem:
If you are on HTML5, use window.postMessage. Just message from iFrame to the parent in the onload of iFrame. Parent should register handler in <script> tag, that appears before iFrame.
Add a callback function to window in the '' tag before iFrame. This function is called by iFrame when it's load is complete. Here is the basic template.
Here is the sample template:
<script>
window.iframeCallback = function(message) {
// first clear the temp function we added to the window
// It is a bad practice to corrupt the global namespace
delete window.iframeCallback;
// you do your work here
};
</script>
..
..
<!-- iFrame should appear after the above script-->
<iframe/>

Javascript pop-up login cross-browser issue

I have a page with an iframe in it. Within the iframe, the default page runs some javascript to open a child window, login to an external service, then display some content from that external service back in the iframe.
My code works fine in Chrome and IE but in Safari and Firefox it does not. In those browsers the parent window seems to ignore that fact that the user is now logged in to the external service and displays their "Not logged in" message instead of the info that is supposed to display.
Here's the code for what I'm trying to do.
HTML (main page):
<iframe id="brief" name="brief" src="contents/somepage.php?var=WXYZ" width="962" height="600">
<p>Your browser does not support iframes.</p>
</iframe>
somepage.php
<html>
<head>
<script type="text/javascript">
window.onload = function()
{
var code = 'WXYZ';
var login = http://www.externalsite.com/brief/html.asp?/cgi-bin/service?msg=0048&usr=username&pwd=pass';
//OPEN CHILD WINDOW AND LOGIN USING VARIABLES ABOVE, THEN CLOSE WINDOW
childWindow=window.open(login,'','width=30,height=30,location=no');
var cmd = 'childWindow.close()';
setTimeout(cmd,2000);
//REDIRECT THIS IFRAME TO BRIEFING INFORMATION
var uri = 'http://www.externalsite.com/brief/html.asp?/cgi-bin/service?msg=0092&AID=NOSEND&MET=1&NTM=1&LOC='+code;
self.location.href=uri;
}
</script>
</head>
<body>
</body>
</html>
I have tried adjusting various setTimeout functions to try to delay certain aspects of the script to wait for something else to happen but it doesn't seem to help.
Is there some cross-browser problem with this code that I am missing?
Thanks
setTimeout(cmd,2000); is not going to block script execution for two seconds; rather, it sets up an event that will fire in approximately 2 seconds. Immediately after your call to setTimeout, the remaining parts of the script will execute:
// This happens right away
uri = 'http://www.externalsite.com/brief/html.asp?/cgi-bin/service?msg=0092&AID=NOSEND&MET=1&NTM=1&LOC='+code;
self.location.href = uri;
The fact that it works in any browser is just lucky timing. If you want the iframe to refresh after the popup closes, add that code to your callback (you don't need to and shouldn't use a string for your timer handler, by the way):
setTimeout(function() {
childWindow.close();
var uri = 'http://www.externalsite.com/brief/html.asp?/cgi-bin/service?msg=0092&AID=NOSEND&MET=1&NTM=1&LOC='+code;
self.location.href = uri;
}, 2000);
Even this solution won't work if the popup's content doesn't load within two seconds. The best solution is to have the popup close itself after loading. Then, you could detect when it closes and know that you're ready to reload your iframe. But if this is a third-party site that you don't have control over, you're probably stuck using a less-than-ideal solution like this.

How to force an iFrame to reload once it loads

I have numerous iframes that load specific content on my pages. Both the parent and iframe are on the same domain.
I have a scrollbar inside the iframe that doesn't seem to load correctly in all browsers. But when I refresh the iframe it loads perfect. I have no idea why it does this.
I have used the meta refresh, which works but I don't want the page to refresh constantly, just once.
The solution I'm looking for will reload the iFrame content after the iFrame is opened, with a minimal delay.
Edit
I realized that my page loads all of my iframes when the index is loaded. The iframes appear in a jQuery overlay, which is also loaded but visibility:hidden until called. So on this call is when I would want the iframe to be reloaded.
Could anyone help me come up with a Javascript function that reloads the iFrame when I click the link to the iFrame? I've gotten close but I know nothing about js and I keep falling short. I have a function that reloads the page, but I can't figure out how to get it called just once.
I have this so far:
<script type="text/javascript">
var pl;
var change;
pl=1;
function ifr() {
if (pl=1) {
document.location.reload([true]);
alert("Page Reloaded!");
change=1;
return change;
}
change+pl;
}
So basically it uses the document.location.reload which works to reload the page. I'm trying to then make pl change to something other than 1 so the function doesnt run again. I've been calling this JS from the body with onLoad.
All the leads on this went dead, but I did find a code snippet that worked. Not written by me, and I don't remember where it came from. Just posting to help someone should they ever have the same question.
<div class="overlay-content"> //Content container needed for CSS Styling
<div id="Reloader">
//iFrame will be reloaded into this div
</div>
//Script to reload the iframe when the page loads
<script>
function aboutReload() {
$("#Reloader").html('<iframe id="Reloader" height="355px" width="830px" scrolling="no" frameborder="0" src="about.html"></iframe>');
}
</script>
</div>
Basically just loads the iFrame source when the window with the iFrame opens, as opposed to the iFrame loading when the original page loads.
Beyond the scope of the original question, however this jQuery snippit works with cross domain iframe elements where the contentDocument.location.reload(true) method won't due to sandboxing.
//assumes 'this' is the iframe you want to reload.
$(this).replaceWith($(this).clone()); //Force a reload
Basically it replaces the whole iframe element with a copy of itself. We're using it to force resize embedded 3rd party "dumb" widgets like video players that don't notice when their size changes.
On the iframe element itself, set an onload:
iframe.onload = function() {this.contentWindow.location.reload(); this.onload = null;};
(Only works if the iframe's location is in the same domain as the main page)
Here's a complete solution to the original question:
<iframe onload="reloadOnce(this)" src="test2.html"></iframe>
<script>
var iframeLoadCount = 0;
function reloadOnce(iframe) {
iframeLoadCount ++;
if (iframeLoadCount <= 1) {
iframe.contentWindow.location.reload();
console.log("reload()");
}
}
</script>
The updated question is not really clear (what's "the link to the iFrame" and where is it in your snippet?), but you have a few issues with the code:
"calling this JS from the body with onLoad", assuming you mean an iframe's body, means the variable you're hoping to use to avoid infinite reloading will get clobbered along with the rest of the iframe's page when it's reloaded. You need to either load a slightly different URL in the iframe (and check the URL on iframe's onload before reloading) or put the flag variable in the outer page (and access it with parent.variableName - that should work I think)
if (pl=1) { should use ==, as = is always an assignment.
change+pl; has no effect.

Javascript resize page onload, can I do this before the page loads, classic asp

I am using the following javascript to resize an iframe. The top level page is written is classic asp and contains and iframe into which I am loading a control which is written in .net and ajax. The issue is, that the page size is dynamic depending on content, and also takes a while to load. What happens at the moment is that the page loads, the ajax control loads and scroll bars appear till the contents is fully loads, and then it is resized to fit correctly. Obviously it would be nice if the page was the correct size in the first place whilst the ajax finishes loading the content. Is there a precursor to the onload event in classic asp that I can use?
I want to stay away from one of those 'loading page' images.
function autoIframe() {
try {
frame = document.getElementById("browse_frame");
innerDoc = (frame.contentDocument) ? frame.contentDocument : frame.contentWindow.document;
objToResize = (frame.style) ? frame.style : frame;
objToResize.height = innerDoc.body.scrollHeight + 10 + "px";
}
catch (err) {
window.status = err.message;
}
}
window.onload = autoIframe;
Thanks, R.
If you just put the script inline (not within a function) within your ASP page, it will be run directly (without waiting for the onload function).
E.g.
<html><head>
<script language=javascript>
// run straight away without waiting for an event
alert ("running inline");
// function which will run when onload event fires
function onloaded() {
alert("onload event");
}
</script>
</head>
<body onload='onloaded();'>Hello World</body>
</html>
That way you can just put your resize code into inline script directly AFTER the IFRAME tags on your HTML page. Hope that helps...

Browser refresh on AJAX with script tags in the response

I'm having some issues with a jQuery AJAX call. My code works fine when I request a page with no javascript in it, but when I have script tags in my code, things start to get weird.
It seems that any script tags referencing external URLs cause the browser to redirect. In firefox, the page goes blank. In safari, the page clears and loads with the content of the AJAX response. In both browsers, the URL doesn't change.
To be specific about my problem; I have a tab control in which I'm trying to embed the walkscore widget. Since it's pretty heavy on the client side, I only want to actually load it once the user clicks the tab it's in. The walkscore AJAX page looks like this:
<script type="text/javascript">
var ws_address = "1 Market St, San Francisco";
var ws_width = "500";
</script>
<script type="text/javascript" src="http://www.walkscore.com/tile/show-tile.php?wsid=MY_WSID">
</script>
Is there some restriction on script tags referencing external sites on AJAX calls? Is there any nice way around this?
-- Edit --
OK I've been playing with it for a bit and have narrowed down the problem a little. Let me try give a better explanation at the same time:
I have two files, index.html and walkscore.html
index.html
function widget() {
var widget = $('#walkscore');
$.get('/walkscore.html', function(data) {
$('#loading').slideUp(function() {
widget.html(data);
loaded[name] = true;
widget.slideDown();
});
});
}
walkscore.html - as shown in the top code block
In index.html, I have a link that calls the widget function. Whenever I click this link, the whole page is replaced by the output of the js file. It happens regardless of the domain the js file is from. It only seems to happen with js files that have document.write in them. It behaves in exactly the same way when I use the $.getScript function, even when it's in index.html
-- Edit --
It seems it has everything to do with the document.write. I made a copy of the walkscore javascript and replaced all occurrences of document.write with jquery.html, and it seems to work properly. I'm (obviously) a js noob. Is this the expected behavior of document.write? How come it doesn't do it when I include the script on a page load?
Load script separately from html content, you can use $.getScript( ).
It has to do with the document.write in the response.. I was able to fix this in Firefox by doing this:
<script type="text/javascript">
// save default document.write function so we can set it back
var write_func_holder = document.write;
// redefine document.write to output text target div
document.write = function(text) {
$('#ad_container').html($('#ad_container').html() + text);
}
</script>
<script language="JavaScript" type="text/javascript" src="javascriptfile">
</script>
<script type="text/javascript">
// reset document.write function
document.write = write_func_holder;
</script>
I'm still getting an issue in Safari where the browser refreshes to a blank page with just the content of the document.write and IE6, IE7 doesn't do anything at all. Firefox works though.
I hope this helps someone figure out what wrong and they in turn can fix the IE6/7 and Safari issues
It happens because of the document.write call. Here's some info on what's going on:
Writing After A Page Has Been Loaded
If document.write() is invoked after a page has finished loading, the entire static (non-script generated) content of a page will be replaced with the write method's parameter. This scenario is most often played out when the write method is invoked from an event handler - whether the method is in a function called by the event handler or alone inside the handler - because event handlers are triggered after a page has finished loading. This is important to know because static content replacement is not always the desired result. Another common scenario for content overwite has to do with writing content to a new window. In this case, the overwrite of blank page is the goal.
(source)
The solution I went with was to eliminate the document.write commands, and replace the content of a div instead. If you're loading an external script, and have no control over it, you can replace the document.write function with your own. It's discussed here:
http://www.webxpertz.net/forums/showthread.php?threadid=11658
Hope that helps someone out there!
Replacing document.write is the way to go. This is shameless self promotion, but if you have a non-trivial case, writeCapture.js handles all the edge cases.
I would first check the response of that script source, maybe something in that causes the unwanted behavior.
I am experiencing the EXACT same behaviour and spent some frustrating hours last night trying to figure out what the problem was and searching for answers to no avail. I'm surprised this is mentioned anywhere in the jquery docs as it seems like a plausible problem not some crazy never-to-be-encountered bug.
Anyway, here's my story in case anyone searches for something related.
I have a jquery enabled page that loads some content into a div using $.ajax(), it all works perfectly. What I needed to do was include one of those twitter retweet buttons that shows a count and enables you to tweet about the content on the page. To do this a simple piece of javascript from them should be included on the page.
<script type="text/javascript" src="http://www.retweet.com/static/retweets.js"></script>
So in theory, that script tag should be returned in the ajax call and jquery should execute it and include the result of it, as I specified the data type as html in the $.ajax() call.
The external script on closer inspection does:
if(!url)
{
var url=window.location.href;
}
if(!size)
var size="big";
var height="75";
var width="54"
if(size=="small")
{
height="22";
width="120";
}
if(!username)
var username="none";
url=url.replace("?", "*");
var src="http://www.retweet.com/widget/button/"+size+"/"+username+"/"+url;
document.write('<iframe src="'+src+'" height="'+height+'" width="'+width+'" frameborder="0" scrolling="no"></iframe>');
Which obviously bombs out on the document.write.
Tonight i'll try the methods in this post and see if they work, thanks for the info.

Categories