Tuesday 7 January 2014

$(document).ready() vs pageLoad()

 

$(document).ready() and pageLoad() are very different behind the scenes.

$(document).ready()

If a browser supports the DOMContentLoaded event (many non-IE browsers do), then $(document).ready() will fire on that event. However, IE can’t safely fire $(document).ready() until the document’s readyState reaches “complete”, which is typically later.

If none of those optimizations are available, window.onload will trigger the event.

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 ofApplication.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 notrefreshed 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.Initevent 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.



 



Source : http://encosia.com/document-ready-and-pageload-are-not-the-same/

No comments:

Post a Comment