in

ASP.NET Weblogs

This Blog

Syndication

Sponsors

Alessandro Zifiglio

Rich ajax applications that do not break if javascript is disabled.

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 :

<%@ 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) ?
                "&amp;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 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>
</html>
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.

Comments

 

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

October 4, 2007 9:38 AM
 

Writing rich applications that do not break if JavaScript is disabled said:

Pingback from  Writing rich applications that do not break if JavaScript is disabled

October 4, 2007 11:41 AM
 

Richard said:

Internet Explorer has supported disabling META REFRESH by domain since v6. The NoScript plugin for Firefox also provides an option to disable this tag. A better solution is to assume that script is disabled until you see the script-initiated request.

In fact, with script disabled, the UpdatePanel works even when EnablePartialRendering is true. The only problem is the number of intrinsic ASP.NET controls which only work if script is enabled  - e.g. the LinkButton control.

October 4, 2007 2:59 PM
 

alessandro said:

hi Richard, good catch. Indeed you are absolutely right. That really slipped my mind. I have updated the code. Thanks!

As for controls that in turn render javascript internally like the LinkButton, they are lacking this type of functionality within.

So a solution off the top of my head  would be to inherit these controls individually and perform this test for js from within their render method, in case of the LinkButton for example, that could be made to render an html input button instead. It is however a lot of work, but doable ofcourse.

A better approach again would be to try and make adapters for these controls, again that too has the work factor which is unavoidable. It's either that or wait for a future release of the .net framework that includes this type of rendering capability out of the box.

October 4, 2007 5:39 PM
 

om said:

Is it possible to check javascript disabled on Java enabled web application?

As currently i am working in a project where we are planning to use Ajax as client is expecting richer interaction.

March 8, 2008 2:01 AM
 

Brooke said:

Hi Om... it is possible in Firefox (I'm sure you can do it in other browsers)

You just go to File > Preferences > Content and check the box that says Enable Javascript

April 13, 2008 3:19 PM
 

aezzell said:

I'm clearly missing something. When I run your code on my local machine or on the server, the behavior is as expected: the availability of JavaScript determines whether the page simply updates the inner time or reloads the whole page, thereby updating both times.

But...

(a) I don't see a querystring. Ever. Shouldn't that appear at least once?

(b) I want to use this functionality to determine what to display on the page: an accordion control if JavaScript is enabled; flat text otherwise.

Is this possible?

Thanks

September 18, 2008 4:55 PM
 

Merugu Vijayakumar said:

I am Sorry, the Above code is not working fine, if i disabled java script. one i disabled the java script and execute the same code in other window. then total page is posting to server. so, ajax is not working.

March 16, 2009 7:40 AM
 

pbb said:

One problem with your code, is that JS-enabled users may copy your URL (including the "supportsjs" parameter) and send it in an email, or share it on social bookmarking sites, and that URL is used by a non-JS-enabled user.

My suggestion is not to split your user-group in JS-enabled and -disabled users, but instead use JS for non-essential enhancements only. Make sure everything works without JS, and then provide an additional layer of fine-tuning that uses JS.

And if you need to use JS for essential code, use the NOSCRIPT tag to provide additional code (included in the same page) for users without JS.

April 18, 2009 4:38 PM
 

alessandro said:

True, js is not essential but being able to degrade gracefully with minimum effort is equally important. noscript element won't get you very far on an ajax savy website. For instance take the updatepanel scenario that is able to degrade gracefully to full postbacks but needs to be enabled on the server. You end up not being able to reuse that feature with the noscript tag approach.

Having alternative code for every instance of dynamic js code you have on a page will soon get overwhelming in terms of development time and maintainence.

I prefer to tweak the current approach I've jotted here and fix the holes it has, as the one you pointed regarding people sharing the url. Unfortunately this is still an idea, and I've not had a chance to use in production code yet since disabling partial postbacks is only half the battle. You still need to fix instances of linkbuttons, dropdownlists with autopostback, textboxes with autopostback e.t.c

Thanks for pointing out the deficiency. Very much appreciated.

April 18, 2009 5:17 PM
 

Nima said:

First of all ... sorry about my poor English grammar! ... and thanks dear Alessandro to share your great idea...

I think this is impossible to build RIA and Dynamic contents without JavaScript and Flash!

I can't imagine Web 2.0 without Frameworks, Libraries, Accordions, Tabs, Sliders, Multiple-level menus, Lightbox's, Carousel's, Form validators, animation effects and so on...

But "Disabled JavaScript" In Web 2.0 slowly turns to another black-hole for developers! (just like IE6 and Microsoft itself! -- sorry I hate monopoly)

and what freaks me out is Microsoft disabled JavaScript in IE8 by default !!!!!?!!!!!

I always worry about my clients JavaScript status! ... specially one with lack of amateur web experience!

Final word ... W3School summery = 95% of users have JavaScript enabled in 2008 & 2009 ... So I use my favorite scripts and don't care about 5 percent!

----

Ohhh, your commenting form not working at all without JavaScript!!! ... I have to enabled my JavaScript  :)))))

May 24, 2009 5:41 PM
 

alessandro said:

Your english is excellent. Thanks for the comment :-)

May 24, 2009 5:48 PM

Leave a Comment

(required)  
(optional)
(required)  
Add