Use Ajax to update progress of process running in codebehind - c#

This is a followup on a question I asked earlier.
Update a Web Page as a Process Runs
I want the webpage to display what stage the process is running using Ajax. After each step in the code behind, a file is overwritten with some text indicating what just happened. I want the webpage to periodically send a request for that file and display its contents using either setInterval or setTimeout. Once the button is pressed, the webpage starts its request cycle and the server begins its time consuming operation.
What I have now...
Script for periodic requests:
<script type="text/javascript">
var d = setInterval("Check()", 3000);
function Check() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
alert("get chrome");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
document.getElementById("s").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "temp/test.txt", true);
xmlhttp.send();
}
/*$(document).ready(function () {
$("#uploadbutton").click(Check());
});*/
</script>
Currently Check() starts running as soon as the page loads. I would like it to only be called once the click event happens. If I define the Check() inside the click event, it doesn't recognize the setInterval and will only check if I click the button again. This isn't a huge problem as I think it will be ok to have the script running. It will just display a "not searching" string. Unfortunately as the file gets updated (and I checked that it was) the page does not display the contents as it gets the response. It just remains the same, then once the codebehind finishes, it resets to the default setting. Can anyone tell me why the page isn't updating?
edit: forgot to mention that the click event has an onclick assigned to the C# codebehind that does the long function. I don't know if I can have the javascript Ajax function running and the C# codebehind going too. The Ajax calls have async = true, but the script part isn't running parallel to codebehind right?
edit again: I changed the script to count upwards. I expected it to continue to count while the codebehind did its thing, but once you hit the button it stops. Once the codebehind finishes it restarts the count. Why doesn't the counting keep going? I expect it to restart once the codebehind is finished, but I thought it would keep counting.

setInterval("Check()", 3000); should be called on the button click event. Don't invoke Click() directly on the button click event, just invoke the setInterval("Check()", 3000); and it will invoke Click() for you.

Related

Delaying Calling JQuery or javascript method from c#

I've got a mixture of JQuery and Ajax partial postbacks on a webforms page and I'm trying to stop the user navigating away from a page without their changes having been saved.
It's working pretty well unless one of the data validators on the page is invalid. There is a jquery method on the submit button that basically nulls the onbeforeunload event. In the event that the validators are invalid, I dont want that to happen, so I turned off the client side validation, and in the method, called Page.Validate(), then if the page was invalid, I tried to register a startup script as described here to reset like so:
if (!Page.IsValid) {
ScriptManager.RegisterStartupScript(this, this.GetType(), "", "setConfirmUnload(true);", true);
return;
}
If I run the click submit and the page is invalid, the call to setConfirmUnload(true) happens, but the method cant be found (presumably because I re-set this up every time a postback happens?
The actual error is " JavaScript runtime error: 'setConfirmUnload' is undefined", possibly because the bindEvents() hasnt yet re-run and therefore created it?
I thnk my problem stems from the fact that I am using partial postbacks and autopostbacks, setting up data as the user modifies the form. By default that blitzes my jquery, so I rebind the jquery calls on document.ready() as well as on postback using
<script type="text/javascript">
// attach the event binding function to every partial update
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function (evt, args) {
bindEvents();
});
</script>
And my Bind Events method looks like:
function bindEvents() {
// stuff removed for brevity here...
$(function () {
// Prevent accidental navigation away
$(':input, select').bind(
'change', function () { setConfirmUnload(true); });
$('.noprompt-required').click(
function () { setConfirmUnload(false); });
function setConfirmUnload(on) {
window.onbeforeunload = on ? unloadMessage : null;
}
function unloadMessage() {
return ('You have entered new data on this page. ' +
'If you navigate away from this page without ' +
'first saving your data, the changes will be lost.');
}
window.onerror = UnspecifiedErrorHandler;
function UnspecifiedErrorHandler() {
return true;
}
});
}
If that's the case, is there a way I can force the script to run after the bindEvents() call has happened?

Trying to use onbeforeUnload and it is firing on every user action ... Why?

I have a small code snippet here, I want this code executed only when the user tries to close the window by pressing the "X" at the top. I want to capture their login credentials The issue is that no matter what action the user takes, pressing a button or pressing the button to submit, this code executes. What am I doing incorrectly? Thank you in advance for your help!
<script type="text/javascript">
window.onbeforeunload = function () {
<% Close_btn(); %>
}
</script>
Here's a jquery example, since I'm too lazy to turn it into pure js, but you should get the idea:
$('#login').on('click',function() {
window.onbeforeunload = function() {};
return true;
);
That way, when they do the other function, you first unset the unload, since you know it will fire anytime the unload happens, you just unset it when it will unload in a way where you don't want that action to happen.

Javascript confirm box blocks background

I have a button in a GridView, and when it is clicked it triggers the
protected void GridView_RowCommand(object sender, GridViewCommandEventArgs e)
event. In there I have some logic and at the end I am registering some javascript that generates a pop up. The issue I am having is that for the confirm pop up when it comes up. It shows a blank screen on the background and when I click cancel it shows it back again, otherwise it navigates to another page... But while the box is up the background is white.
I need to make it so that it shows like the "Alert" pop up that still shows the website in the background. Please note I can only make this work with these pop ups as they are used throughout the website ("not confirm ones"). This is the first confirm box I have had to add but there are many Alerts on other pages. So would not like to change them as it will be too much work (150+ pages website).
Thank you
It looks like the page isn't getting a chance to render before the alert box shows up. Hook up the code that displays the JavaScript alert to something like the body.onload event; this will wait for the page to finish its initial load before displaying the alert.
Page.ClientScript.RegisterClientScriptBlock(
this.GetType(),
"key",
#"
function Redirect() {
location.href = 'shoppingCart.aspx';
}
function showAlert() {
if (confirm('***Message truncated***.') == true){
Redirect();
};
}
// If you're using JQuery, you could do something like this, otherwise you
// would need to add the function call to the HTML body tag's onload attribute.
// There are other alternatives, see:
// http://stackoverflow.com/questions/1235985/attach-a-body-onload-event-with-js
$(document).ready(function() {
showAlert();
});
", true);

JQuery causing postback in .NET

I created an adrotator in jquery for the first time and when I use it on a page that uses pagemethods to do ajax calls to the server and show a modal. The page posts back. When I remove the rotator the page works as it should. In the rotator I have the following code in the document ready function.
$(".animation_control a.play").live('click', function () {
$(this).removeClass('play');
$(this).addClass('pause');
Play();
});
$(".animation_control a.pause").live('click', function () {
$(this).removeClass('pause');
$(this).addClass('play');
clearInterval(timer);
});
$(".animation_control a.pause").click(function () {
});
//Toggle Teaser
$("a.collapse").click(function () {
$(".main_image .block").slideToggle();
$("a.collapse").toggleClass("show");
});
If I comment out this code the page stops the complete page refresh and and posts back async like it should. Any ideas on why this would cause the page to do a complete postback instead of a partial one?
As a guess, since the code is incomplete, you should add return false to your event handlers to prevent the links from actually firing.
.live('click', function (e) {
e.preventDefault();
//your code
Anchors are used to navigate to a page/region in the same page, and according to this part, clicking an anchor MUST move us to the HREF that the anchor is pointing to.
in order to cancle this default behavior, we will need to do either return false or to prevent the default action using jQuery.
This is an example of what i mean.

Javascript event like window.onload for subsequent loads

We have a function that changes the iframe height at the window.onload event so we can adjust it to the page contents. The problem is that after clicking in an asp:menu the height its restored to its default and the window.onload event doesnt fire...so we need the event that would fire in subsequent loads (tried window.unload but didnt trigger)
The resize function cant be called on the asp:menu click because the window wouldnt have finished loading so the height calculation would fail...
Any ideas??
ASP.Net AJAX exposes a client event model. To execute code after the content is refreshed, use this to bind to the pageLoaded event:
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedFunction);
Learn more about all of the ASP.Net AJAX JavaScript events here: http://msdn.microsoft.com/en-us/library/bb386417.aspx
ASPNet uses background calls via AJAX and then updates the interface.
You should use servr-side code. Inspect the AJAX resolver you're using and look for its declared events. I'm sure there's one event that triggers after updating a webpage and you can attach an eventListener to it.
I had this same problem with a similar script 2 years ago. I solved it using JavaScript in the newly loaded page's window.onload to call up to the parent document and execute the script. In the child page we had this script:
function goSetHeight(){
if (parent == window) return;
else parent.setIframeHeight('iframe_name');
}
// Edit: Forgot to add the window.onload call
window.onload = goSetHeight;
This script called up to the parent page where we had a script file included that had this function:
function setIframeHeight(iframename) {
var iframeEl = document.all[iframename];
var iframeWin = window.frames[iframename];
if(iframeEl && iframeWin) {
//var docHt = getDocHeight(iframeWin.document);
//if(docHt) iframeEl.style.height = docHt + 30 + "px";
iframeEl.style.height = iframeWin.document.body.offsetHeight + 30 + "px";
}
}
Please note that the above function was written solely with IE in mind (it was an application specification), so to be usable cross browser it would need modification. The only real problem we encountered with it were 2 particular cases:
We had a couple of instances where the pages that were loaded in the iframe were from a different domain than the page holding the iframe. This causes a JavaScript security error because the browser thinks this is an XSS attack and denies it.
We also encountered several situations where the iframe was nested 2 deep. It was a hack-job work-around that I came up with that I was extremely unhappy about, but it worked while we refactored from classic asp into .Net. I have since lost the script that was used to perform the pass through, but it wasn't complicated, it simply performed a similar parent check and kept going.
In the end we used a hiddenfield where we saved the height calculated in the window.onload
document.getElementById("iframex").value = document.getElementById("iframeheight").height;
...then in the Menu1_MenuItemClick(object sender, MenuEventArgs e) we reassigned the height to the iframe: iframex.Attributes["height"] = iframeheight.Value;
This works for us (Because in our case luckily the page height doesnt change on each option selected) but doesnt resolve the original question about getting fired the window.onload event or something similar after subsequent loads in order to recalculate the new height...
We will wait so someone can give the best answer to this problem...

Categories

Resources