Why Javascript not works with Master Page

| September 22, 2010 | 12 Comments

This article tries to explain answer to why javascript not works with Master Pages in Asp.Net. Before we delve into deepness of the solution; it would be nice to have an insight about the problem, the reason behind the problem. And finally we will arrive at solution.

Problem

I am developing web application using asp.net. My application is having single .aspx page (Default.aspx) and other one .master page(MasterPage.master) with their respective .cs files. I am having four controls on .aspx page only. Two are Textbox and two are Button controls. I am trying to achieve objective of making button controls enabled to true (as they are already disabled by default). So for that I have tried following piece of code:

Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"
    MasterPageFile="~/MasterPage.master" %>

<asp:Content ID="FirstContent" runat="server" ContentPlaceHolderID="ContentPlaceHolder1">

    Email:
    <asp:TextBox ID="txtEmail" runat="server" /><br/><br />
    Mobile:<asp:TextBox ID="txtMobile" runat="server" /><br />
    <asp:Button ID="btnEmail" runat="server" Text="Email" Enabled="false" />
    <asp:Button ID="btnMobile" runat="server" Text="Mobile" Enabled="false" />
</asp:Content>

Default.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;</pre>
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
txtEmail.Attributes.Add("OnKeyDown", "document.getElementById('btnEmail').disabled=false");
txtMobile.Attributes.Add("OnKeyDown", "document.getElementById('btnMobile').disabled=false");
}
}

But when I tested this code it was unable to make button controls enabled. And sometimes we get error as Microsoft JScript runtime error: ‘document.getElementById(…)’ is null or not an object. So what caused this abnormal behavior of program & above error?

Reason of Problem

So before trying for reason, let us see the source page of the .aspx page in browser by right clicking in browser window & selecting View Page Source option. Below is the code snippet from source page:

<div>
 Email:
 <input id="ctl00_ContentPlaceHolder1_txtEmail" onkeydown="document.getElementById('btnEmail').disabled=false" type="text" name="ctl00$ContentPlaceHolder1$txtEmail" />

 Mobile:<input id="ctl00_ContentPlaceHolder1_txtMobile" onkeydown="document.getElementById('btnMobile').disabled=false" type="text" name="ctl00$ContentPlaceHolder1$txtMobile" />

 <input id="ctl00_ContentPlaceHolder1_btnEmail" type="submit" name="ctl00$ContentPlaceHolder1$btnEmail" value="Email" disabled="disabled" />

 <input id="ctl00_ContentPlaceHolder1_btnMobile" type="submit" name="ctl00$ContentPlaceHolder1$btnMobile" value="Mobile" disabled="disabled" /></div>

Now as you can see ID of button control has changed to somewhat like ct100_ContentPlaceHolder1_btnMobile instead of btnMobile. And that is why javascript function is not executing correctly because there doesn’t exist any Id with btnMobile in Html page generated.

The reason of conversion of ID is that when MasterPages are used they tend to rename all the controls in Content pages which have attribute runat=”server”. However controls which are not having runat=”server” would have their ID same (no conversion).

Solution

We would need to use the changed ID of these controls for which we want to run our javascript code. And for this we will use Asp.Net inline tags & ClientID properties of control. ClientID is something that is generated automatically by Asp.Net for server when the control is rendered as Html ID of the control.

Now we have changed our code little bit from above. See below code:

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"
    MasterPageFile="~/MasterPage.master" %>

<asp:Content ID="FirstContent" runat="server" ContentPlaceHolderID="ContentPlaceHolder1">

    <script type="text/javascript">
    function  EnableEmail()
        {
          if(document.getElementById("<%=btnEmail.ClientID%>").disabled==true)
          {
             var email=document.getElementById("<%=btnEmail.ClientID%>");
             email.disabled=false;
          }
        }

        function  EnableMobile()
        {
          if(document.getElementById("<%=btnMobile.ClientID%>").disabled==true)
          {
             var mobile=document.getElementById("<%=btnMobile.ClientID%>");
             mobile.disabled=false;
          }
        }
    </script>

    Email:
    <asp:TextBox ID="txtEmail" runat="server" /><br/><br />
    Mobile:<asp:TextBox ID="txtMobile" runat="server" /><br />
    <asp:Button ID="btnEmail" runat="server" Text="Email" Enabled="false" />
    <asp:Button ID="btnMobile" runat="server" Text="Mobile" Enabled="false" />
</asp:Content>

Default.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;</pre>
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
txtEmail.Attributes.Add("OnKeyDown", "EnableMobile()");
txtMobile.Attributes.Add("OnKeyDown", "EnableEmail()");
}
}

And so now if you see Source code of Html page you would see that the ClientID is same as of the generated (or converted) ID. And hence javascript code starts working as expected.

Tags: , ,

Category: Asp.Net, Tips

Comments (12)

Trackback URL | Comments RSS Feed

  1. Anonymous says:

    Thank you Very Much

  2. V.S. Saini says:

    1. Are you using Asp.Net 4.0 for development of website? If yes, then you can set

    <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <pages clientIDMode="Static"/>
    </system.web>

    in web.config file. And then try to access the element.

    2. I assume tabid is id of asp:menu. View the page source of html rendered in browser. And check if the same element exists with same id name or modified id.

    I hope that the particular element would be there with modified id with something as ct100_tabid. Then try to use the id which is displaying there.

    Let us know the result. And if possible share the code with us.

  3. var menuitems=document.getElementById(tabid).getElementsByTagName("a")

    the above line is in yellow color while executing….

    it says Microsoft JScript runtime error: ‘document.getElementById(…)’ is null or not an object

    wat to do plz help me

  4. V.S. Saini says:

    @Mike Marks:

    Yes! I agree with you. That problem has been resolved with applications developed in .Net 4.0.

  5. Mike Marks says:

    It doesn’t matter if the page is a master page or not. All server-side controls get renamed regardless. Client-side controls do not get renamed.

    .NET 4.0 offers an additional attribute to server controls called “ClientIDMode”. For example:

    This keeps the ID the same even after the page is rendered.

  6. scazorlay says:

    If control is in same Master Page, it doen’t work. My situation: I’ve txt in master page and I want that, when get focus, all content dissapears. Any help will be appreciated a lot!

    Thanks

  7. Anonymous says:

    Thankyou so much.

  8. Anonymous says:

    Thank you! Helped me a lot :)

  9. Anonymous says:

    I am using javascript with Master page too, but in my case ur solution did not work. Can u please give any suggestions…Have been so in hard time with this problem!!

    Here is my javascript:

    window.onload = function () 
    {
      var strCook = document.cookie;
        if (strCook.indexOf("!~") != 0) 
        {
           var intS = strCook.indexOf("!~");
           var intE = strCook.indexOf("~!");
           var strPos = strCook.substring(intS + 2, intE);                   document.getElementById("%=divGvIncidentDetail.ClientID%>").scrollTop = strPos;
        }
     }
    
  10. V.S. Saini says:

    Thanks Anton for positive and appreciable feedback. Would inspire me to carry on knowledge sharing.

  11. Anonymous says:

    Thank you VERY much for that solution, today you are my favourite person as I’ve been bettling with this issue for 2 days straight now. Once again, thanks a million!

  12. Anton says:

    Thank you VERY much for that! You are a legend in my eyes, I’ve been battling with this for 2 days straight! Once again, thanks… and once I saw the solution you go like “damn I’m stupid, it’s actually so obvious, of course the controls will be renamed…” :o)

Leave a Reply

%d bloggers like this: