$(document).ready() and pageLoad() are not the same!
AJAX, ASP.NET, JavaScript, jQuery By Dave Ward. Posted March 25, 2009Note: This post is part of a long-running series of posts covering the union of jQuery and ASP.NET: jQuery for the ASP.NET Developer.
Topics in this series range all the way from using jQuery to enhance UpdatePanels to using jQuery up to completely manage rendering and interaction in the browser with ASP.NET only acting as a backend API. If the post you're viewing now is something that interests you, be sure to check out the rest of the posts in this series.
Recently, I’ve attended several presentations in which ASP.NET AJAX’s pageLoad() shortcut is demonstrated as interchangeable with jQuery’s $(document).ready() event. The suggestion that both methods are equivalent actually appears to be true in simple demos, but is not the case and is certain to lead to later confusion.
While they seem similar on the surface, $(document).ready() and pageLoad() are very different behind the scenes. Determining the earliest point that it’s safe to modify the DOM requires a bit of black magic, and the two libraries approach that in their own unique ways. Additionally, pageLoad() is overloaded with some extra functionality which may surprise you.
In this post, I’ll clarify the major differences between jQuery and ASP.NET AJAX’s initialization functions, what implications those difference have in practice, and show you a third alternative when working with ASP.NET AJAX.
Under the hood: $(document).ready()
As you would expect from John Resig, jQuery’s method for determining when the DOM is ready uses an assortment of optimizations.
For example, if a browser supports the DOMContentLoaded event (as many non-IE browsers do), then it will fire on that event. However, IE can’t safely fire until the document’s readyState reaches “complete”, which is typically later.
If none of those optimizations are available, window.onload will trigger the event.
Under the hood: pageLoad()
Instead of targeting browser-specific optimizations, the ASP.NET AJAX pageLoad() shortcut function is called as a result of a more uniform process.
That process is queued up the same way on all browsers, via a call to setTimeout with a timeout of 0 milliseconds. This trick leverages JavaScript’s single-threaded execution model to (theoretically) push the init event back until just after the DOM has finished loading.
Counter-intuitively, this isn’t the only point at which pageLoad() is called. It is also called after every partial postback. It basically functions as a combination of Application.Init and PageRequestManager.EndRequest.
Danger: UpdatePanels ahead
Since pageLoad() is called after every UpdatePanel refresh, the complications that arise can be initially difficult to grasp. For example, you’ll often see code like this:
<script type="text/javascript"> function pageLoad() { // Initialization code here, meant to run once. } </script> <asp:ScriptManager runat="server" /> <asp:UpdatePanel runat="server"> <ContentTemplate> <asp:Button runat="server" ID="Button1" /> <asp:Literal runat="server" ID="TextBox1" /> </ContentTemplate> </asp:UpdatePanel>
That initialization code will execute on the initial load, and things will seem okay at first. However, pageLoad() will then continue to be called each time Button1 is triggered, resulting in the initialization code running more often than intended.
This problem is similar to the classic ASP.NET mistake of forgetting to test for IsPostBack during the server-side Page_Load event. Depending on the nature of your initialization code, you may not even notice that there’s a problem, but it’s bound to catch up with you eventually.
In the case of initialization code that should run once, $(document).ready() is the ideal solution. It will do exactly what you need and nothing more.
Sometimes, pageLoad() is exactly what you want
While $(document).ready() is ideal for one-time initialization routines, it leaves you hanging if you have code that needs to be re-run after every partial postback. The LiveQuery functionality added in jQuery v1.3+ helps with this, but only works for a limited set of functionality.
For example, what if we wanted to add a jQueryUI datepicker to the TextBox in the previous example? Adding it in $(document).ready() would work great, until a partial postback occurred. Then, the UpdatePanel’s new TextBox element would no longer have the datepicker wired up to it. This is exactly where pageLoad() shines:
<script type="text/javascript"> function pageLoad() { $('#TextBox1').unbind(); $('#TextBox1').datepicker(); } </script> <asp:ScriptManager runat="server" /> <asp:UpdatePanel runat="server"> <ContentTemplate> <asp:Button runat="server" ID="Button1" /> <asp:TextBox runat="server" ID="TextBox1" /> </ContentTemplate> </asp:UpdatePanel>
By attaching in pageLoad(), our TextBox will now have the datepicker attached to it on initial page load, and have it re-attached after every partial postback.
The call to unbind() is optional in this case, but a good precaution on more complex pages. Else, you run the risk of stacking multiple events on elements that were not refreshed as part of the partial postback.
An ASP.NET AJAX alternative to $(document).ready()
The previous sections should make it easier to decide between jQuery and ASP.NET AJAX’s events, but they assume you’re using both frameworks. What if you’re only using ASP.NET AJAX and want functionality similar to $(document).ready()?
Luckily, ASP.NET AJAX does provide a corresponding event. The Application.Init event fires only one time per page load, and is perfect for onetime initialization tasks. It’s not available through a shortcut function and requires slightly more caution, but serves its purpose:
<asp:ScriptManager runat="server" /> <script type="text/javascript"> Sys.Application.add_init(function() { // Initialization code here, meant to run once. }); </script>
Note that the call to Application.add_init is placed after the ScriptManager. This is necessary because the ScriptManager injects its reference to MicrosoftAjax.js in that location. Attempting to reference the Sys object before that point will result in a “sys is undefined” JavaScript error.
If you think that limitation is a bit messy, you are not alone. I’m not a big fan of littering my presentation code with any more inline JavaScript than is necessary. To avoid this clutter, you may alternatively include your Application.Init code in an external file, included via a ScriptReference (see the previous link for an example).
Summary (tl;dr)
$(document).ready()
- Ideal for onetime initialization.
- Optimization black magic; may run slightly earlier than pageLoad().
- Does not re-attach functionality to elements affected by partial postbacks.
pageLoad()
- Unsuitable for onetime initialization if used with UpdatePanels.
- Slightly less optimized in some browsers, but consistent.
- Perfect for re-attaching functionality to elements within UpdatePanels.
Application.Init
- Useful for onetime initialization if only ASP.NET AJAX is available.
- More work required to wire the event up.
- Exposes you to the “sys is undefined” error if you aren’t careful.
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.
9 Mentions Elsewhere
- DotNetShoutout
- Reflective Perspective - Chris Alcock » The Morning Brew #315
- $(document).ready() and pageLoad() are not the same! | Encosia - DotNetBurner
- Sys.Application initialization steps « Update Panel .NET
- Jquery e UpdatePanel « MaxCNunes
- another .NET developer » استفاده همزمان از jQuery و ASP.NET AJAX UpdatePanel
- Code.AdamJZeffer.com - Centering a pop up on a scrolled page
- jQuery and Telerik RadControls « Code Chex
- Jquery won’t work after partial postback in ASP.NET « Powertips



Come on Dave, join the resistance. Drop MS AJAX and go JQuery solo! You know you want to. :)
Good post btw.
thnks it really works
Really helpful article….
If i use only jQuery, what is the equivalent to pageLoad()? How can i reatach the datepicker function in a textbox for exemple?
if i use only jQuery to make ajax calls, the textbox is never unbinded, correct?
There’s nothing exactly like
pageLoad()in jQuery, because it doesn’t have anything like the UpdatePanel either.It depends on what’s happening after the AJAX call. If you’re doing something to remove the textbox from the DOM and re-create it as part of your AJAX callback, then you’ll still need to reapply the datepicker afterward. The place to do that would be in the
successhandler of that particular AJAX call.Thanks! Have not run into this one yet, but it is only a matter of time. Thanks for the great heads up.
Hi Dave.
First of all I would like to say congratulations for your article: it’s very detailed and high valued!
I’ve written a blog post recently about how you can use jQuery live() for one-time initialization without losing attached functionality to items that are in UpdatePanels.
I’ve also written about how welcome pageLoad() is and where it isn’t recommended to use.
You can read the post here: jQuery live() and ASP.NET Ajax asynchronous postback
jQuery live(): binds a handler to an event (like click) for all current – and future – matched element. Hence your attached functionality is still available after an asynchronous postback.
The live() event is of course bound to event values like: click, mouseout, mouseover, etc. So this is a limitation you need to take care of.
I’m with Chris JQuery rocks MS AJAX is to heavy
I keep hearing about multi-threaded javascript implementations showing up in browsers in the future. Let’s hope that this doesn’t cause any issues with Microsofts hacky solution to the page load problem. And I use the term “hacky” loosely here, since almost everything dealing with the DOM seems hacky.
The setTimeout-0 thing is pretty widespread at this point. I believe it was originally popularized by Dean Edwards.
I’m assuming multi-threaded engines will have to have an opt-in setting or something similar. Else, multi-thread JavaScript engines would “break” so many sites that no one would want to use browsers running those engines.
fantastic article! back when asp.net ajax first came out i started playing with it and i had this one-time init problem in pageLoad() — i remember it drove me crazy! i kinda figured it out on my own but it was never really documented. soon after i discovered jQuery — i’ve been in heaven since…
thanks for the article — thanks for clearing it up!
That pretty well describes my trial and error process of originally learning how pageLoad() really works too. I know the feeling!
Nice article. I just want to add that one may check if pageLoad event is called after a partial load or as a result of full page refresh by checking the isPartialLoad property of the passed event argument. Similar to the following:
function pageLoad(sender, args) {
if (args.get_isPartialLoad()) {
alert(“Ajax call”);
} else {
alert(“PostBack or initial load”);
}
}
There was also bit about the difference between pageLoad and window.onload on stackoverflow recently you may find interesting.
http://stackoverflow.com/questions/602441/whats-the-different-between-asp-net-ajax-pageload-and-javascript-window-onload/#603116
Thanks, Not Good but Fantastic Article.
Your blog is awesome!
Hi,
Thanks for the detailed article.
In writing a self-contained server control that requires code to run after every partial postback I am using pageLoad() but I would like to have some input as to which is the best way to subscribe to this event being mindful that the host page might define its own pageLoad() and other server controls might also need to independently subscribe to it also.
Also R, thanks for the tip with the args.
Regards,
Chris.-
Application.add_load() allows you to handle that same event without using pageLoad(). pageLoad() is called immediately after all of the handlers registered through Application.add_load().
If you only want to run code after partial postbacks, not also the initial load, PageRequestManager.EndRequest may be a more appropriate event for your control.
Thanks for the quick reply, just found it on the reference also… good to have confirmation, I forgot to mention I do want it to run also on the initial load, this is perfect.
I’m using jQuery now to handle things like highlighting table rows when they’re rolled over.
So, before I read your post, I was solving the problem by sending back script to re-run document.ready() in server-side event handlers. Works… but obviously, your solution is WAY better!
So–THANKS!
Great post, Dave!
If it’s of any help, I put together a “cheat sheet” with client life-cycle events a while back. I also wrote a similar post on Sys.Application.add_load vs window.onload.
Cheers!
Milan
Excellent post! Very helpful. Thank you, Dave.
Excellent post. Solved my problem.
Thanks a lot buddy…
Good article!
Great post
Using pageLoad is ok for date picker and JQuery, but it does not appear to work in Chrome / Safari, only IE.
Richard
Great post man!
– Lee
Great post man!
nice article..
Hello, See this.
$(document).ready(function() {
iniciareventos();
var scriptManager = Sys.WebForms.PageRequestManager.getInstance();
if (scriptManager) {
scriptManager.add_endRequest(eventosP);
}
});
function eventosP() {
$(“.x”).click(popmsg);
$(“.xx”).click(popmsg);
$(“.xxx”).click(popmsg);
$(“#logo”).click(logocl);
}
function iniciareventos() {
$(“#logo”).hide();
$(“#comu”).hide();
$(“#estadisticas”).hide();
$(“#trabasignados”).hide();
$(“#graficos”).hide();
$(document).ready(mostrar);
eventosP();
}
Thanks! Helped me a lot. Great blog
Great article, congratulations. Thank you, Dave.
And what’s about the difference between Sys.onReady() in ASP.Net Ajax and $(document).ready() in jQuery. Are those “the same” ?
Thanks
Sys.onDomReady() is closer to $(document).ready(). Sys.onReady() doesn’t fire until any Sys.Requires registered scripts have loaded too.
I don’t think either of those functions made it out of the Ajax Library before they stopped working on it though.
thanks, was just what I needed because I had a gridview in asp.net and used the plugin tablesorter, but selecting an item of lost orden.Finalmente gridview using your code, it worked:
Thanks again
Thank you so much man ! I’ve been looking for like a week now for the solution of my problem. This seems to have fixed it !
Much love ! <3
Great post. It seems hard to find information regarding how both frameworks are different but could be used to get the job done in different scenarios.
Thanks!
Excellent article, and fixed my problem.
Cheers
Ok so I’ve been searching the web for quite some time and cannot for the life of me solve this problem. How do I get the Jquery datepicker control to work inside a textbox inside a template field inside an asp.net detailsview control inside an updatepanel? Please someone end my search!
Thank you,
Mark
You’re probably running into the ClientID problem. Take a look at this post (and its comments) for ways to mitigate that issue: http://encosia.com/2007/08/08/robust-aspnet-control-referencing-in-javascript/
in Place of this script
function pageLoad() {
$(‘#TextBox1′).unbind();
$(‘#TextBox1′).datepicker();
}
I used this script to solve the MASTER page problem.
function pageLoad() {
$(‘.TextBox1′).unbind();
$(‘.TextBox1′).datepicker();
}
I am using update panel and jquery validation
first time validation works completely but after one post back validation dont work.
i have tried to use pageLoad() method but it dont go inside when i debug.
provide proper solution.
i got it correct using pageLoad() method.
actually problem was because of using pageLoad() method multiple time.
by merging code into single method solves problem.
thanks. :)
great article!
Awesome. Your unbind on page_load fixed my issue.
Great explanation. Fixed the problems I was experiencing! Thanks
Great article!!!!
Really interesting article, i have lots of confusion between init and pageload function of ajax.
Thanks for sharing such wonderful article, keep this good work.
Thanks Dave ! You saved my day !
This article is a lifesaver! Thank you so much!
Hi, great article !
I think it will solve my problem but I’d appreciate a little help.
I have a ASP.NET Timer and when it Ticks I call asynchronously web service method that returns me a photo. I have a in Update Panel and update it src when I get a photo. I’m using a jQuery lightBox plugin to preview a image. The mechanism works but on a partial postbacks image loses attatched plugin. So I need re-attaching functionality to elements within UpdatePanels.
I attach plugin with:
As it is said pageLoad() should solve the problem, but how to modify this js to use pageLoad ? How sholud look my js script ? I’m a begginer with js so please help me. Moreover, should I attach sth to my project to use pageLoad() ?
Thanks in advance for Your help.
If it’s just the one UpdatePanel, you should be able to fix that by changing your JavaScript to this instead:
Hi, thanks for reply.
I’ve got four UpdatePanels. In each a different image (each UpdatePanel has own Timer trigger and WebService). But all UpdatePanels will be within div with id ‘gallery’ and I will place function pageLoad() only once, outside UpdatePanels. So lightBox functionality should work for all my images, doesn’t it ?
And one more question, sholud I install some library to my project to use function pageLoad() ?
That’s right, the
pageLoad()function is going to run once when any UpdatePanel refreshes (and it will also run ones on the initial page load too). So, if your jQuery selector,#gallery amatches all of those images, it will apply to them regardless of any UpdatePanel divisions.You won’t have to install any extra libraries.
pageLoad()is something that MicrosoftAjax.js calls automatically if it’s included on the page. When you have a ScriptManager on the page (which you must have to use UpdatePanels, of course), one of the things it does is include MicrosoftAjax.js. So basically, if you’ve got an UpdatePanel then you can usepageLoad().I really appreciate your help. Thanks for clear answer.
Was doing something fancy with jQuery UI inside a ListView inside an UpdatePanel. You know the rest… :)
Was searching for the correct Sys. and stumbled upon pageLoad.
Can’t remember everything you write it seems. Thanks a lot!
Hello,
Thanks, this post is really interresting.
I would like to add a fix to a problem that I faced recently regarding the autopostback and the textchanged event of textboxes in a update panel : http://aelassas.free.fr/blog.html#post27
Kind regards,
This is what I am looking for :) Thank you very much
Man, I had a problem with Telerik’s RadTreeView, in IE8, and I was searching the whole Internet to find an answer. Alas, they don’t support that fine. However, by reading your post and by understanding the difference between pageLoad() and $(document).ready(), I got the clue to solve the problem.
And, to me, Microsoft’s setTimeout() seems a genus work.
Thanks.
I was having this exact issue … Have every time my page partially posted back I lost all of my js funcationality pageLoad() worked perfect. Thx!
Hi Dave,
Nice article, but my problem is really unique. I have posted on many forums,but no help, i got struct with this issue from one month. Your help is really appreciated.
I have a master page a
Inside page 1 I have a grid and onclick on it it opens a new page 2
Inside page 2 i have a update panel and inside update panel I have a user control
Inside usercontrol there is a grid (third party tool Obout grid)
When a postback happens in usercontrol , my grid stops working.
it is kind of disabled.
Please help me on this.
Vani
T Y !!!!!!
Hi newbie in jquery/ajax here. I cant figure out how to solve this problem. The problem i have is, when btnSubmit is clicked, everything is working fine. But when i click btnClear, jquery stops working. This is a simplied version, the actual code has a gridview instead of lblMessage. Also in actual code btnClear is in each row in the gridview. Any pointer will be greatly appreciated:
Thanks Dave.
I was having same issue with ajax, jquery together and resolved using your article by using the pageLoad() {//initialization code}
Thanks Dave,
Very nice and easily understandable article.
That did the trick for me as well – thanks for posting this!
Very nice post really very useful
Great. Saved life :) thanks.
Thank you very much Dave,
Your post helped me to solve my issue with ajax update panel and pageload, ready functions.
I have used this and other solutions in your site to make a simple asynchronous refresh of two labels (that take time to generate and render on the server). But I am seeing a side effect: if the user goes down to read more content while the labels are being generated, as soon as they are rendered, the browser “jumps back” to the start of the page, so the user has to go down again.
You can go to my site (http://limitedsecurities.com) to see it, while the section “news” and “tweets” are being generated you can go down, as soon as any of those two are rendered, the browser sends you back to the start of the page.
This is the code within my .aspx file
<form ID="FormNewsPage" runat="server"> <asp:ScriptManager ID="ScriptManagerNewsPage" runat="server"></asp:ScriptManager> <div class="threecolumn"> <h2>News</h2> <ul class="smallbox news"> <asp:UpdatePanel ID="UpdatePanelNews" runat="server" UpdateMode="Always"> <ContentTemplate> <asp:Image ID="ImageNews" runat="server" ImageUrl="./images/loading.gif" /> <asp:Label ID="LabelNews" runat="server"></asp:Label> <asp:Button ID="buttonUpdateNews" OnClick="btnUpdateNews_Click" runat="server" Text="" style="display:none"></asp:Button> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="buttonUpdateNews" EventName="Click" /> </Triggers> </asp:UpdatePanel> </ul> </div> <div class="threecolumn last"> <h2>About Us</h2> <ul class="smallbox"> <li> ... text ... </li> </ul> <h2>Our Tweets</h2> <ul class="smallbox twitter"> <asp:UpdatePanel ID="UpdatePanelTwitter" runat="server" UpdateMode="Always"> <ContentTemplate> <asp:Image ID="ImageTwitter" runat="server" ImageUrl="./images/loading.gif" /> <asp:Label ID="LabelTwitter" runat="server"></asp:Label> <asp:Button ID="buttonUpdateTwitter" OnClick="btnUpdateTwitter_Click" runat="server" Text="" style="display:none"></asp:Button> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="buttonUpdateNews" EventName="Click" /> </Triggers> </asp:UpdatePanel> </ul> </div> <script language="javascript" type="text/javascript"> document.getElementById('<%= buttonUpdateNews.ClientID %>').click(); Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler); var myFlag = true; function endRequestHandler(sender, args) { if (myFlag == true) document.getElementById('<%= buttonUpdateTwitter.ClientID %>').click(); myFlag = false; } </script> </form>Any idea how to solve this problem? Thanks in advance!
If I were fixing that, I would replace the UpdatePanel approach with something like this: http://encosia.com/boost-aspnet-performance-with-deferred-content-loading/
Then, you could have both asynchronous content loads in parallel and injecting the content shouldn’t affect scroll position.
Dave,
I fixed it as you suggested, you can see it working properly here: http://www.limitedsecurities.com/default.aspx … amazing results, thanks A LOT!!!
Regards,
Miguel
Excellent post. It solved one of my big issue. Thanks a lot.
Thank you Dave,
Your post has been really helpful!
Awesome dude.You are amazing in explaining the concepts at the most detailed level.
hello,
i need your help in resolving an issue with jquery. i have a function like this one:
it is meant to load only when an error occurs in a button click event. the code for the click event is this:
The problem is the jquery function keeps firing even when the page loads or is refreshed. Please is there a way to make it execute only when the condition is met ? Kindly help…
You don’t need to wrap the function declaration in a document ready event wireup since you only intend to call it later.
$(document).ready()is only for code that you intend to run immediately after the page loads. You should simply declare the function like this:Then, it should only execute when you call it from your
RegisterStartupScriptcall.Dave…thanks. Its ok now.