I have a page that performs a long-running task (10 to 15 seconds) in the page_load method.
I have client-side javascript code that will display a decent "page loading" animated gif to the user.
I am able to invoke the JavaScript method from the code-behind, to display the "page loading" animated gif, however, the long-running task is hanging up the UI such that the animated gif doesn't actually display until after the long-running task is complete, which is the exact opposite of what I want.
To test this out, in my page_load method I make a call to the JavaScript method to display the animated gif. Then, I use Thread.Sleep(10000). What happens is that the animated gif doesn't display until after Thread.Sleep is complete.
Obviously I am doing something incorrect.
Any advice would be appreciated.
Thanks.
Chris
Below is an example of the code-behind:
protected void Page_Load(object sender, EventArgs e)
{
ClientScript.RegisterStartupScript
(GetType(), "Javascript", "javascript: ShowWaitIndicator(); ", true);
Response.Flush();
Thread.Sleep(10000);
}
I accomplished this by placing a timer on the page. After its first tick disable it and run your task.
<asp:Timer runat="server" id="UpdateTimer" interval="500" ontick="UpdateTimer_Tick" />
I placed this within an UpdatePanel for my needs. I'm not sure what will work best for you. Then in your code behind...
Protected Sub UpdateTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
UpdateTimer.Enabled = False
' run method here
End Sub
The reason is that the Page.Load event fires before any response has been sent to the client; so any instructions for the client (such as executing your javascript) doesn't occur until the client receives the response.
So... placing the long-running task in Page.Load won't have the effect you want. This sounds like a case for using AJAX or some other form of asynchronous data-retrieval. In this scenario the page you return to the client doesn't containt he result of your long-running task--so the page itself (with it's spinner) loads quickly, then the client requests the data; when the data is ready (10-15 seconds later) you can update the DOM in the client with the results.
Following example will work for you. just place in Page Load Event.
Response.Write("<div id=\"loading\" style=\"position:absolute; width:100%; text-align:center; top:300px;\"><img src=\"http://www.cse.iitk.ac.in/users/singhroh/images/loading.gif\" border=0></div>");
Response.Flush();
System.Threading.Thread.Sleep(5000);
Response.Write("script>document.getElementById('loading').style.display='none';</script>");
I would avoid invoking your JavaScript from the code-behind.
Instead, utilize the jQuery library. You can trigger your code to be called immediately after the DOM is loaded by using the following code:
$(document).ready(function() {
//Call your JavaScript method here.
});
You'll also need to add jQuery to your page, which is a single script include from the Microsoft CDN. Add this to your markup to do this:
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js"></script>
This will call your GIF JavaScript method immediately when the page is loaded and you can eliminate your Thread.Sleep. I'm assuming your animated GIF method automatically hides the image after 10-15 seconds.
Taking it old school, you could switch buffering off. With buffering on (the default), the page is generated in it's entirity before it's sent to the client. If you switch buffering off, it's sent as it's loaded, so you can send the html to switch the loading graphic on, do your long running task, then send some javascript to switch it off.
It sounds like the Javascript onload is being displayed after the ASP onload processes. You may want to delay your time-intensive action to Page.LoadComplete - this way, your user will see the Javascript render before the intensive operation occurs.
Then, you would update the page contents as needed after the function completes.
Can you provide an example of the code?
Related
I have some long code on server side that runs on Page_Load(). My problem is that users don't see nothing until this code is over
I want to show them some loading picture so that they will know that something is happening. I tried to put some JavaScript alert() on page but it didn't helped. I tried to changed html from server-side but of course it only shows the changes after job is done.
protected void Page_Load(object sender, EventArgs e)
{
// show user a loading image
// start heavy coding
}
You can use AJAX or UpdatePanel to separate loading and user-visualizing processes.
In this case you just need pageLoad() - js function, which will call proper, for example, web-service-method and shows loading image. OnSuccess\OnError events if ajax call will help you to handle the result of this call
I have a form with a browser control. (this control uses IE9 because I set values on registry editor)
This web browser navigates to a specific URL and fills all fields on HTML page and submit them, then result page is displayed.
My problem is that i just want to know when this reslut page is fully loaded or completed so that i can fetch some information.
I use WebBroswer_DocumentCompleted event which works fine for the first page but not for the result page as it triggers before result
page is loaded.
I tried other solution which is to check the div tag inside the result page (this tag only appears when result page is loaded completely) and it works but not always.
My code:
private void WebBroswer_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
HtmlElementCollection elc3 = this.BotBrowser.Document.GetElementsByTagName("div");
foreach (HtmlElement el in elc3)
{
if (el.GetAttribute("id").Equals("Summary_Views")) //this determine i am at the result page
{
// fetch the result
}
}}
That div id is "Summary_Views".
I can provide you the link of that website on demand which is just for BLAST tools and database website for research purpose.
Frames and IFrames will cause this event to fire multiple times. Check out this answer:
HTML - How do I know when all frames are loaded?
Or this answer:
How to use WebBrowser control DocumentCompleted event in C#?
Or ms's kb article:
http://support.microsoft.com/kb/180366
Do you know if there are frames? If so then please say so, so people can help with that. If not then say so, so people can offer alternatives.
My guess is that the content is being generated by JavaScript. If it is then the document is complete before the JavaScript executes and you need to somehow wait until the JavaScript is done. The solution depends upon the web page. So you might need to process multiple document completes for diagnostic purposes and attempt to determine if there is a way to know which one you need.
At last i have solved my problem. I put a timer control from toolbox and set its time interval to 200ms and its Autoreset property to false. I set a tick event which has a code to check every 200ms whether this Div has been loaded or not, after that, Autoreset property is set to true.This solution is working perfectly :)
I have a function inside my .aspx.cs code which takes wuite a long time to do the processing until when I want to display a cool loading animation. I looked some of the earlier posts but either these didn't work for me, or were having solution specific to Page loading scenario (not loading a while a function completes).
I guess the right approach would be to fire a Javascript startLoader() function just before the the main function starts (which takes a long time), and then call a stopLoader() from the .aspx.cs itself to stop the loader when the function ends. Any suggestions how to implement this?
Yes, I've done this in ASP.NET Web From (not a ASP.NET MVC solution). You need to provide OnSubmit client side event handler. It basically break down to three parts: Javascript, HTML Div, and one line code behind:
Javscript:
function ShowLoading(e) {
// var divBg = document.createElement('div');
var divBg = document.getElementById('blockScreen');
var divLoad = document.createElement('div');
var img = document.createElement('img');
img.src = 'images/ajax-loader.gif';
divLoad.setAttribute("class", "blockScreenLoader");
divLoad.appendChild(img);
divBg.appendChild(divLoad);
document.getElementById('blockScreen').style.display = 'block';
// These 2 lines cancel form submission, so only use if needed.
//window.event.cancelBubble= true;
//e.stopPropagation();
}
function HideLoading() {
//alert('hideloading');
document.getElementById("form1").onsubmit = null;
document.getElementById('blockScreen').style.display = 'none';
//alert('done');
}
Add following DIV
<div id="blockScreen" class="blockScreen" style="display:none"> </div>
Finally, add the following to Page_Load in code behind.
Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), "submit", "ShowLoading()");
Now, all of your page postbacks are essentially have to call onsubmit event. It will display the animation before the page postback finishes.
if you really want to do, then the only way is webworkers. You've probably heard about them, or if not, i seriously recommend to have a look.
Yes, fire startLoader() on OnCliencClick of your button or whatever element you are using to fire the server-side event and call stopLoader() from the server-side at the end of your process. Something like this:
//rest of the server-side code above ...
Page.ClientScript.RegisterStartupScript(this.GetType(), "someKey", "stopLoader();", true);
If you don't mind that the browser is not responsive in the meantime, the simplest way of doing this is using an animated gif:
Activity indicators
ajaxload.info
webscriptlab
The trick is showing the image when starting your processing, and hiding it when finished. You can show it in an img, and use jQuery or whatever you want to show/hide it.
If you need the browser to keep responsive, use Web Workers. But be aware that some of the older browsers don't support it. See this reference
I am working on a web application where I want to show a loading image (busy indicator) when my code create a xml file and download it I want to show the image in a div. I should use c# code only not update panel nor the jquery ajax technique. My code looks like:
protected void lb_DownloadXML_Click(object sender, EventArgs e)
{
this.imgLoading.Visible = true;
//all my code
this.imgLoading.Visible = false;
}
my image is
<img src="Images/loading_big.gif" width="50" height="40" runat="server" id="imgLoading"
visible="false" />
but its not working. Can anybody explain me how can I achieve this task.
thanks in advance.
To execute server side code from client machine, there is no other way other than UpdatePanel or Ajax. The client request should reach to the server to execute the request. And the way this happens is by PostBack or by Get request. PostBack will reload page, if you are not using UpdatePanel (I guess which you don't want) and second is GET, which again you don't want.
Update
According to #Lloyd
Yes it is possible, you can render contents to the page sequentially by setting the "Response.BufferOutput" property to false, writing directly to the Response.Output and Flushing the stream.
You should well understand that when you write any code on server side it is only reflected in the broswer after a successful postback. Over here if you write C# code to display an progress image then it would be displayed only after the postback is successful, that means after your XML file has been created and downloaded to the client end or after successful execution of lb_DownloadXML_Click().
So there is no way to achieve that using C# server side code, you have to rely on client side programming to achievev this.
I have found out it is possible to execute javascript after an UpdatePanel has updated it's contents, but is it possible to execute javascript as soon as the trigger is fired?
I could probably hack some messy javascript, but I was wondering if ASP.NET had any 'inbuilt' functionality?
Quote from MSDN - endRequest Event:
The endRequest event is raised after an asynchronous postback is finished and control has been returned to the browser.
In other words you can attach a javascript handler function to the beginning and ending of a partial postback (when the update panel updates).
In the example on the page, you can see that the handler is attached using the PageRequestManager:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler)
For reference purposes:
beginRequest - Start of the Request.
endRequest - When the request is completed.
UpdatePanel usage implies full page life cycle to be triggered again, so you should be able to catch the document ready, in jQuery terms, like this:
$(function() {
// Handler for .ready() called.
});
see here: http://api.jquery.com/ready/
I guess there are a few options here you could obviously do something like the following.
<div id="Container" onclick="__doPostBack('UpdatePanel1', '');">
But any of the page life cycle events could be used here is an excellent resource on what and when everything gets called.