I wonder if there is way to run JS code whenever a asp.net page is contacting the server.
I.e. I'm looking for a general event handler that is triggered whenever a call to the server is made for runat="server" components.
I know there's a way to get jQuery.ajax() to run JS code before and after a call to the server is made, but I'm not sure how to do it in asp.net. Especially, since this projects uses a lot of custom components.
The goal here is to show some kind of loading image when a button is clicked, to prevent the user to click a button twice and also to show the user that the system is working.
If the click causes the page or an updatepanel to refresh, I'd only like to display the loading image before the refresh, eg. User clicks, "loading" is shown, page/update panel is refreshed (causing the "loading" to disappear), the new page/content is displayed as normal.
Update 1:
I can't use UpdateProgress because some of the buttons aren't inside UpdatePanels. What I really want to do is to fire a JS as soon as any button/control that will contact the server is clicked. I.e. if the user clicks a dropdown which doesn't contact the server, nothing should happend. But if that dropdown has any connection to the server, a JS should be run.
I understand that this is ASP.NET Ajax and not jQuery Ajax, I only used jQuery as an example. Because I've used a jQuery method before (with jQuery Ajax) to trigger JS before the server call was made. Eg. to lock the element that was clicked or to display a "Loading..." screen.
I could of course add a bit of a JS hack to every page which adds a "onclick" event to every button manually, but I thought it would be better if there was a general solution for this (since I've got lots of pages, each with a few buttons that contact the server on them).
Update 2:
When I think about it, it doesn't necessarily need to be a JS that is triggered. It would be good enough if the page somehow only made sure that the same button wasn't clicked twice. Either by disabeling the button or by adding something in front of it (like a "Loading..." screen).
You can use an UpdateProgress for this to use with update panels, but if you are doing a full page postback (i.e. not ajax) the only loading animation you can have is the browsers own.
UpdateProgress:
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
Shiny loading aninmation
</ProgressTemplate>
</asp:UpdateProgress?
Here is how you can do it using jquery:
$(function() {
$('a[href]').on('click', function(e) {
var self = this;
e.preventDefault();
loadAsync($(self).attr('href'));
});
});
function loadAsync(url) {
$('div#result').fadeOut(200, function() {
$('div#loader').fadeIn(200, function() {
$.get(url, function(data) {
$('div#result').html($(data));
}).done(function() {
console.log('done');
}).fail(function() {
$('div#result').html('Error');
}).always(function() {
$('div#loader').fadeOut(200, function() {
$('div#result').fadeIn(200);
});
});
});
});
}
I am using ASP.Net AJAX UpdatePanel to load the right part of the page.
As that part will take some time to load, I would like to load it after the other parts of the page is loaded.
I can use either normal AJAX or ASP.Net AJAX but I chose to use the latter as I want to try it out.
I found out that my UpdatePanel is always loaded.
I want it to be loaded only after the page is ready.
Some says to use the timer, some says to use some javascript.
But I still can't get it done.
So, these are my 2 obstacles, to stop loading when the page starts and to start loading when the page is ready
why don't you enable and disable on page events? for example. try in Page_PreLoad event, set the update panel's enable property to False. While in Page_LoadComplete event, set it back to enabled = true
UpdatePanels use Ajax to update, not on first load.
If you want it to load quickly on first load, avoid any expensive processing, database calls on load. Put them in an
if(IsPostBack)
{
//your long processing
}
Now use an AsyncPostBackTrigger to make your updatePanel postback.
try with this code ( Conditional Mode + Update Method)
<asp:UpdatePanel ID="YourIdPanel" UpdateMode="Conditional" runat="server">
//In order to force loading
YourIdPanel.Update();
<script type="text/javascript">
var currentItemID=$('#<%= labcurrentItemID.ClientID %>').html();
if (currentItemID != null) {
$(document).ready(function () {
$('#main_container').load('/Custom/Going%20Places/PopularRelatedArticle.aspx?currentID=' + currentItemID);
});
}
else {
$(document).ready(function () {
$('#main_container').load('/Custom/Going%20Places/PopularRelatedArticle.aspx?currentID={7F0811A7-D484-4675-8A23-0AEB235B9B5F}');
});
}
</script>
I have 6 thumbnail images as asp:imagebutton instances. These are treated as triggers for asp:updatepanel control on the page which contains an asp:image control.
When the user clicks on the thumbnail, the image in the asp:updatepanel's image control changes to the clicked thumbnail image.
The users are also allowed to again enlarge the image by clicking on the enlarge button (this runs the lightbox function). This works fine.
Question
The problem is that the enlargement works when the page loads, however when the user select a thumbnail and then tries. The method (lightbox) does not work.
I have had similar problems with javascript functions and the asp:updatepanel. Has anyone else faced similar issues? If so, how do I solve this issue?
A $ function (which is a DOM ready function) will be only be executed when the page loads for the first time.
Any further AJAX call (which is a partial loading/rendering) will not fire DOM ready function. Which is the reason, you were not able to get it working.
In you case, this function binds your anchor link (button) with the lighbox behavior the first time the page loads. so, it works. The next time when you refresh the update panel (which is a partial render) the button is not bound to lightbox again. Unless this binding is achieved it will not show up.
Normally a script control is used in such cases to fire the event every time the control is loaded.
If you are not bothered here about segregating related objects, the solution like pageLoad is still fine.
Following javascript was defalut one, it work fine without asp:UpdatePanel
<script type="text/javascript">
$(function()
{
$('#gallery a').lightBox();
});
</script>
but it is not working with asp:UpdatePanel so there is the need to call function on page load and it works fine.
<script type="text/javascript">
function pageLoad(sender, args)
{
$('#gallery a').lightBox();
}
</script>
Thanks guys for helping.
Solved:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<script src="../slimbox-2.05/slimbox2.min.js" type="text/javascript"></script>
<script type="text/javascript">
function pageLoad() {
jQuery(function ($) {
$("a[rel^='lightbox']").slimbox({/* Put custom options here */
}, null, function (el) {
return (this == el) || ((this.rel.length > 8) && (this.rel == el.rel));
});
});
}
</script>
I've just determined using Firebug that when Fancybox window is created it actually takes all of my ASP.NET controls (contained in DIV tag) and puts them outside FORM tag. So I guess this is the reason why then ASP.NET button doesn't do anything - it is placed outside form.
So, do you have any suggestions how I can prevent this (or make that ASP.NET button work), other than using completely different modal dialog?
EDIT: OK, people are reporting that some of the proposed fixes are working for them on certain versions. So, be sure to read all of the answers / scroll to the bottom for how to fix this issue on different Fancybox versions.
You need to change this (somewhere around line 719 of jquery.fancybox-1.3.1.js):
$('body').append(
tmp = $('<div id="fancybox-tmp"></div>'),
loading = $('<div id="fancybox-loading"><div></div></div>'),
overlay = $('<div id="fancybox-overlay"></div>'),
wrap = $('<div id="fancybox-wrap"></div>')
);
to
$('form').append(
tmp = $('<div id="fancybox-tmp"></div>'),
loading = $('<div id="fancybox-loading"><div></div></div>'),
overlay = $('<div id="fancybox-overlay"></div>'),
wrap = $('<div id="fancybox-wrap"></div>')
);
For anyone needing a simple answer to this problem using Fancybox version 2 theres a much easier way of doing it. All you have to do is add parent: "form:first" in the code eg
$(document).ready(function () {
$(".various").fancybox({
parent: "form:first",
fitToView: true,
width: '300px',
height: '100px',
autoSize: false,
closeClick: false,
openEffect: 'none',
closeEffect: 'none',
modal: false
});
});
then this will append the fancybox elements in the dom inside the form tag, rather than inside the body tag.
Fancybox Version 2.1.4
Change these 2 lines
Around Line 2069 :
document.all && !document.querySelector ? $('html') : $('body');
to
document.all && !document.querySelector ? $('html') : $('form:first');
and around Line 1960 :
this.overlay = $('<div class="fancybox-overlay"></div>').appendTo('body');
to
this.overlay = $('<div class="fancybox-overlay"></div>').prependTo('form');
You could also use appendTo but that's up to you. In my case I needed prependTo.
I've been trying to figure out this problem all week, I haven't really had any luck
I just came across this article
http://usmanshabbir.blogspot.com/2010/10/click-server-button-problem-in-jquery.html
That explains how to get postback working with the jQuery UI Dialog box.
If it's not 100% necessary to use fancy box then this method is definitely worth a try, it's saved me a lot of hassle today.
Without altering the FancyBox source, put this after the FancyBox script (outside any load events!!!):
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/#.#/jquery.min.js"></script>
<script type="text/javascript" src="/fancybox/jquery.fancybox-#.#.#.pack.js"></script>
<script type="text/javascript">
// Override $.fancybox.init to fix ASP.NET PostBack bug;
var fancyboxInitOld = $.fancybox.init;
$.fancybox.init = function () {
fancyboxInitOld.apply(arguments);
$("#fancybox-tmp, #fancybox-loading, #fancybox-overlay, #fancybox-wrap").appendTo("form:first");
};
// Your code ...
</script>
jquery.fancybox-1.3.4.js line 1040
//$('body').append(
$('form').append(
tmp = $('<div id="fancybox-tmp"></div>'),
loading = $('<div id="fancybox-loading"><div></div></div>'),
overlay = $('<div id="fancybox-overlay"></div>'),
wrap = $('<div id="fancybox-wrap"></div>')
);
Works (my asp:Button does postback) for me on FF and IE9, thanks for the solution
The above update didn't work for me, the fancybox was still added outside the form. I then commented out those 6 lines in jquery.fancybox-1.3.2.js and found they weren't being used at all in my code.
I did a search on 'body' in the fancybox js files and changed it to 'form' in:
jquery.fancybox-1.3.2.js (ln 484)
jquery.fancybox-1.3.2.pack.js (ln 27, ln 41)
The fancybox is now getting added to the form and the server controls are working.
Fancybox Version: 2.1.2
Line 1782 of jquery.fancybox.js
Change this:
this.el = document.all && !document.querySelector ? $('html') : $('body');
To this:
this.el = document.all && !document.querySelector ? $('html') : $('form:first');
I use Fancybox 1.3.4 to show an aspx page as a popup page in fancybox iframe. But button in the popup page does not cause postback. I did not change anything as you said before. Rather I did the following.
function check()
{
var validated = Page_ClientValidate();
if (validated) {
__doPostBack('<%=bur.ClientID%>','');
parent.$.fancybox.close();
return true;
}
else
{
return false;
}
}
<asp:Button ID="bur" runat="server" Text="ser"
OnClientClick="check()" />
protected void bur_Click(object sender,Eventargs e)
{ //put breakpoint here.
}
Fancybox 1.3.4 actually does postback.
But if is closed in OnClientClick that is before server side click event it wont postback .So The above is the solution to this problem.(Adding doPostBack in javascript function).
Normally Fancybox 1.3.4 does postback without any change in its .Js files. But to close it , need to write this line ScriptManager.RegisterClientScriptBlock(this, GetType(), "", "parent.$.fancybox.close();", true); in server side click event. Only then both serverside event gets called and fancybox also closes.
But Fancybox 2.1.3 (latest) does postback event after it is closed in OnClientClick.
If refreshing the parent is a solution which serves the purpose, you can refresh onClosed:
$(".fancybox").fancybox({
'onClosed': function() {
parent.location.reload(true);
}
});
Without any change in fancybox js library file, what works for me was below,
$('.your-selector').fancybox({
afterShow: function () {
$('.fancybox-overlay').appendTo('form');
}
});
I have moved the fancybox div inside the form tag, and now, server side button is working like a charm :)
All the best.. I hope this will work for you too. .:)
You don't need to change any code or any library... Just try this..
$('.fancybox').fancybox({
parent: "form:first", // jQuery selector
});
Heres the worst solution possible, however it worked for me. I needed faceybox and codebehind at the same time. Setup your fancy box to load when button clicked. Then onClosed pass values to another C# page and do the code behind on Page Load.
<script type="text/javascript">
$(document).ready(function () {
$(".fancy").fancybox({
onClosed: function () {
window.location.href = "worker_addcarrier.aspx?name=" + document.getElementById('<%=txt_carriername.ClientID%>').value +
"&password=" + document.getElementById('<%=txt_password.ClientID%>').value +
"&email=" + document.getElementById('<%=txt_email.ClientID%>').value;
}
});
});
and then just the "class=" thing here:
<asp:Button ID="Button1" href="logo.png" runat="server" class="fancy" Text="Create" Width="109px" BorderColor="#009933" OnClick="Button1_Click" />
I have a data repeater in ASP.NET page. It loads lots of stuff and its taking 4 - 5 seconds to display images. I can' t page or get a part of items i need to display all of the data so i need a loading message or gif but how can i do that? Can anyone help me?
Thanks
If your scenario is not ajax one (classic form postback or browser is redirected by link-click)
I'd insert animated gif into html layout just before redirection / post back (hidden div is shown or something like that). AFAIK this approach will have problems with old-day-browsers (animation will be frozen)
Another approach is called page-processor?. Browser is redirected to intermediate page that shows animation while page requested is loaded.
You can also send javascript code from server (Response.Write / Response.Flush) that will animate your current page.
I also advise to block/hide UI control such as "send form" to deny impatient user click twice if server is responding too long.
Use an iframe. Essentially you can open a slow running page in an iframe and use the events raised by the iframe to display a loading image.
<script type="text/javascript">
var t;
//on iframe state change display or hide the loader tag
function readyStateChanged(state)
{
if (state == 'complete' || state == 4 || state == '4' || state == 'Complete')
{
//hide the loader
document.getElementById('loader').style.display = 'none';
clearTimeout(t);
} else
{
//diaplay the loader
document.getElementById('loader').style.display = '';
//hide the loader if the iframe never loads
t = setTimeout("hideLoader()", 5000);
}
}
//hide the loading tag
function hideLoader()
{
document.getElementById('loader').style.display = 'none';
clearTimeout(t);
}
</script>
<div id="loader" style="display: none;"><img />loading...</div>
<iframe id="frameX" src="your_page.aspx" width="100%" height="400px" onload="hideLoader();" onreadystatechange="readyStateChanged(this.readyState);" ></iframe>