Always wanted to test if the client's browser has javascript
disabled in their browser ? Sounding impossible ? Well, not anymore!
Ok, so as Web2.0 applications are increasing in popularity and we
are all starting to enable a lot of clientside javascript in our web
applications, especially the use of ajax extentions and the
updatepanel, we also know how this is all going to break for users who
have javascript turned off or whose browsers do not support javascript.
Now, lets be real, it's not very common nowadays for a
useragent to not support javascript, all the big players support it
well(IE, Firefox, Opera, Safari).
However what about users that
have javascript turned off ? Personally, I don't want my applications
breaking on potential clients who fall in this category and
realistically, today, there is no way to test for sure if the client
turned off javascript. Sure, I am aware of the HttpBrowserCapabilities
class, specifically the EcmaScriptVersion property.
However this is a
pretty useless property to me in this usage scenario since it only
tells me what version of javascript the users client browser supports.
This is simple static information passed on by the clientbrowser when
making the request.
What we need is to know "Is javascript
turned off ?" Knowing this is important in today's applications because
it allows us to gracefully exit, or provide a serverside alternative, a
non script version of our page being requested.
As of this
writing I have not found any clear answer anywhere, so i have invested
a couple of minutes to come up with the following solution. It's quite
simple and should be working 100% without breaking, telling us exactly
what we are seeking. -->> Hey, you there making the request, do
you have javascript enabled/disabled ?
The idea is to
introduce a piece of js code when the first request is being made by
the client. Particularly a piece of code that can tell us serverside,
"yes, javascript is enabled", without any delay or rendering much
content to the client.
|
<script type="text/javascript"> window.location.href= "http://weblogs.asp.net/Default.aspx?supportsjs=true"; script>
|
if javascript is enabled, the clients page will redirect, but what if
js is disabled ? this script wont do anything, so to address this, we
will introduce a second piece of code as well :
|
<meta http-equiv="refresh" content="0;url=http://weblogs.asp.net/Default.aspx?supportsjs=false" />
|
That's it. If js is disabled, this second line will kick off and postback. Perfect.
Still,
we don't want to do this everytime. We want to do this for the first
request only, so what we can do is set a serverside flag in session
state. I don't really recommend using session state because I find
sessions to be unreliable, but that's just me.
You basically have no
control on when the session recycles. My preference lies in the profile
provider(which is going to persist the value in the database and in
style), however for simplicity, i'm setting a flag in session state.
Update october 4th,2007 :
Initially, as you have read above in this post, i was planning on using the meta refresh tag if js was indeed disabled on the client. It was also a useless effort, when I couldof just assumed js was disabled from the start and only enabled if the js script fired the postback.
As you will note from Richards comment below, the meta refresh tag only brings other problems to the table as it can in turn be disabled invidividually by the browser and not only in IE or Firefox but opera has support for this too. Here is the updated code that checks for javascript without meta refresh tag getting in the way.
Following is the code :
| ASP.NET |
|
|
<%@ Page Language="C#" %>
<script runat="server">
/*
do it in init, otherwise you cannot
set ScriptManager.EnablePartialRendering property
*/
protected void Page_Init(object sender, EventArgs e)
{
bool notSet = string.IsNullOrEmpty(
this.Request.QueryString["supportsjs"]);
string url = this.Request.Url.OriginalString;
if (notSet && Session["supportsjs"] == null)
{
string queryStringKey = (this.Request.QueryString.Count > 0) ?
"&supportsjs=" : "?supportsjs=";
string jsTesterScript = string.Format(
"<{0} type=\"text/javascript\">window.location.href='{1}{2}true'</{0}>",
"script", url, queryStringKey);
Response.Write(jsTesterScript);
Response.Flush();
}
if (Session["supportsjs"] == null)
Session["supportsjs"] = false;// default, assume false
// if our js code posted back,
// and we still hold default assumption,
// then client does indeed support js
// so update the session
if (!notSet && !(bool)Session["supportsjs"])
Session["supportsjs"] = true;
ScriptManager1.EnablePartialRendering = (bool)Session["supportsjs"];
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<h1>outside updatepanel : <%= DateTime.Now %></h1>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<h1>Inside updatepanel : <%= DateTime.Now %></h1>
<asp:Button ID="Button1" runat="server" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
<div>
</div>
</form>
</body>
|
I have tested the above code to work flawlessly in IE, Firefox, Opera
and Safari. I've enabled and disabled javascript in the browsers during
testing and as simple as the code may seem, it works.
This is indeed
great because now your rich ajax web applications can cater nicely to
all targets and not break in the face of who has javascript disabled.