Friday, April 24, 2009

2 Ways to Load jQuery from an ASP.Net Master Page

If you're getting started with using jQuery in ASP.Net, you'll probably come across a situation where you would like to load it from a Master Page so that it's available globally for all Content Pages. When you do so you'll find that you get assorted errors for different reasons.

After reading many articles and much trial & error I have determined two different approaches to get it working. Note: My preference is to separate all code from the markup as much as possible. So directly in the root of all my projects is a folder called "Javascript". Inside it I always place [at least] these 3 files:
  • jquery-1.3.2.js
  • jquery-vsdoc.js
  • main.js

Approach #1: Entirely from the Markup Page

<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="placeHolder1" runat="server">
<script src="<%= Page.ResolveUrl("~/JavaScript/jquery-1.3.2.js") %>" language="javascript" type="text/javascript"></script>
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
<script src="<%= Page.ResolveUrl("~/JavaScript/jquery-vsdoc.js") %>" language="javascript" type="text/javascript"></script>
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<script src="<%= Page.ResolveUrl("~/JavaScript/main.js") %>" language="javascript" type="text/javascript"></script>
</asp:ContentPlaceHolder>
</head>

<body onload="$(document).ready(main)">


Approach #2: Entirely from Server-side Code

protected void Page_Load(object sender, EventArgs e)
{
AddScript(Page.ResolveUrl("~/JavaScript/jquery-1.3.2.js"));
AddScript(Page.ResolveUrl("~/JavaScript/jquery-vsdoc.js"));
AddScript(Page.ResolveUrl("~/JavaScript/main.js"));

string jScript = "$(document).ready(main);";
ScriptManager.RegisterStartupScript(Page, Page.GetType(),
Guid.NewGuid().ToString(), jScript, true);

}

private void AddScript(string src)
{
HtmlGenericControl genCtrl = new HtmlGenericControl();
genCtrl.TagName = "script";
genCtrl.Attributes.Add("type", "text/javascript");
genCtrl.Attributes.Add("language", "javascript");
genCtrl.Attributes.Add("src", src);
Page.Header.Controls.Add(
genCtrl);
}


I hope this helps others! Please be aware that most everything above applies generically to all Javascript code, not just jQuery.

6 comments:

  1. Hi,

    Good post. I want to share with all, jquery-vsdoc.js is for VS2008 SP1 IntelliSense. It is the same content as jquery-1.3.2.js but fully commented, so the file size larger. There is no need for client browser to load it. VS only want it writen in the markup page to enable IntelliSense during typing JavaScript/jQuery there. So the tweak is make ContentPlaceHolder1 hidden or use like this:
    <% If False Then %>
    <script type="text/javascript" language="javascript" src="<%= Page.ResolveUrl("~/JavaScript/jquery-vsdoc.js") %>" ></script>
    <% End If %>
    as stated in by ScottGu here: http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx

    Also I notice the file name in front of '-vsdoc.js' should be the same to enable IntelliSense properly. so jquery-1.3.2.js should be renamed as jquery.js or jquery-vsdoc.js rename as jquery-1.3.2-vsdoc.js. but so far I also use different name and still works as long as both is there. Just -vsdoc.js hidden from client.

    One more thing, my opinion, body onload and $(document).ready do the same thing. So the proper way is just write <body onload="main()"> or add this anywhere:
    <script type="text/javascript" language="javascript">
    //<![CDATA[
    $(document).ready(main);
    //]]>
    </script>

    LaNN

    ReplyDelete
  2. Excellent Post!!

    If you don't use Content placeholder then it will give you error for "&lt%%&gt".

    Second method is also superb and it works like a charm. if you directly put below line

    "this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(),"Global",this.ResolveClientURL("~/Script/BrowserDetection.js"));"

    in page_load event, it will work but it will add javascript link reference in body tag rather than Head tag and it may cause problem while you are using User Contro.

    Thanks for this post, it's really helpful. :)

    ReplyDelete
  3. Thanks mate! This was the exact thing i was looking for....and my headache (caused by the errors i was receiving before i implemented your code) disapeared ;-)

    Cheers,

    Andreas van Bergen

    ReplyDelete
  4. ..onload="$(document).ready(main)" ..

    You should never use onload method to execute javascript code that messes with DOM. The onload event is first executed when EVERY element on the page has finished loading.

    jQuery ready event will be triggered when the DOM is ready.

    You can read more about here: http://www.learningjquery.com/2006/09/introducing-document-ready

    And btw, why not loading jQuery from Google or Microsoft? :)

    ReplyDelete
  5. I thought it would never work, after positioning in many places in many ways, including codebehind etc. But eventually I worked out that you need to declare paths just before your 1st div. In this case where my Jquery action started. I also used the Resolve URL method to reference the path. Stoked 100%. Ignore the "`" in the s`cript and d`iv words.

    " language="javascript"
    type="text/javascript">
    " language="javascript"
    type="text/javascript">
    " language="javascript"
    type="text/javascript">

    ReplyDelete