Determine if a user enables JavaScript
I made a post over on my business' blog about the general concept of my post today, determining if a user has JavaScript enabled.
This is sort of a touchy subject since Microsoft has their own AJAX stuff and they pretty much do what they want with that. But what about ASP.NET developers like me that write their own JavaScript? There isn't much support since we can't use their source code. They probably have something in their code that determines if a user has JavaScript enabled. Even if they did, I wouldn't want to put their AJAX DLL in a site in which I don't use ASP.NET AJAX.
So the solution is to check whether the user has it enabled or not and to render stuff based on that finding.
What my solution does is pushes a input control onto a page, changes the value, and does a postback. If the postback gets the data it wants, the SessionState value of the JavaScript key is set to Enabled. I use a WebControl and a helper class to accomplish this. I make use of SessionState since I hate ViewState with a passion :)
Here's the code (in VB):
Helper Class
Imports System.Web Namespace EagleEnvision.MainSite.Utilities Public Class JavaScriptDetection Public Shared Sub SetValue(ByVal isEnabled As Boolean) If isEnabled Then SetValue(JavaScriptState.Enabled) Else SetValue(JavaScriptState.Disabled) End If End Sub Public Shared Sub SetValue(ByVal state As JavaScriptState) HttpContext.Current.Session(SessionValue) = state End Sub Public Shared Function GetState() As JavaScriptState Return CType(HttpContext.Current.Session(SessionValue), JavaScriptState) End Function Public Shared Function IsEnabled() As Boolean Select Case GetState() Case JavaScriptState.Enabled Return True Case Else Return False End Select End Function Public Const SessionValue = "IsJavascriptEnabled" Public Enum JavaScriptState Enabled Disabled Undefined End Enum End Class End Namespace
Web Control
Imports System Imports System.Collections.Generic Imports System.ComponentModel Imports System.Text Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports EagleEnvision.MainSite.Utilities.Constants Imports EagleEnvision.MainSite.Utilities Namespace EagleEnvision.MainSite.Controls Public Class DetectJavascript Inherits WebControl ' generated hidden field properties Private hiddenID As String = Me.ID + "_jsdetection" Private value As String = "x" Private ReadOnly Property DoesNeedValidation() As Boolean Get Return (Utilities.JavaScriptDetection.GetState() = JavaScriptDetection.JavaScriptState.Undefined) End Get End Property Protected Overloads Overrides Sub RenderContents(ByVal output As HtmlTextWriter) If DoesNeedValidation() Then Dim c As String = "<INPUT type=""hidden"" id=""" + hiddenID + """ name=""" + hiddenID + """ />" output.Write(c) Dim script As String = "<script language=""javascript"" type=""text/javascript"">" script += "document.forms[0]." + hiddenID + ".value = """ + value + """;" script += "document.forms[0].submit();" script += "</script>" output.Write(script) End If End Sub Protected Overloads Overrides Sub OnLoad(ByVal e As EventArgs) MyBase.OnLoad(e) Dim isEnabled As Boolean = False If DoesNeedValidation() And Page.IsPostBack() Then If HttpContext.Current.Request(hiddenID) = value Then isEnabled = True End If JavaScriptDetection.SetValue(isEnabled) End If End Sub End Class End Namespace
Line needed in the Global.asax
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) JavaScriptDetection.SetValue(JavaScriptDetection.JavaScriptState.Undefined) End Sub
Here's the code (in C#):
Helper Class
using System.Web; namespace EagleEnvision.MainSite.Utilities{ public class JavaScriptDetection{ public static void SetValue(bool isEnabled){ if (isEnabled) SetValue(JavaScriptState.Enabled); else SetValue(JavaScriptState.Disabled); } public static void SetValue(JavaScriptState state){ HttpContext.Current.Session[SessionValue] = state; } public static JavaScriptState GetState(){ return (JavaScriptState)HttpContext.Current.Session[SessionValue]; } public static bool IsEnabled(){ switch (GetState()) { case JavaScriptState.Enabled: return true; default: return false; } } public const SessionValue = "IsJavascriptEnabled"; public enum JavaScriptState{ Enabled, Disabled, Undefined } } }
Web Control
using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using EagleEnvision.MainSite.Utilities.Constants; using EagleEnvision.MainSite.Utilities; namespace EagleEnvision.MainSite.Controls{ public class DetectJavascript : WebControl{ private string hiddenID = this.ID + "_jsdetection"; private string myvalue = "x"; private bool DoesNeedValidation { get { return (Utilities.JavaScriptDetection.GetState() == JavaScriptDetection.JavaScriptState.Undefined); } } protected override void RenderContents(HtmlTextWriter output){ if (this.DoesNeedValidation){ string c = "<INPUT type=\"hidden\" id=\"" + hiddenID + "\" name=\"" + hiddenID + "\" />"; output.Write(c); string script = "<script language=\"javascript\" type=\"text/javascript\">"; script += "document.forms[0]." + hiddenID + ".value = \"" + myvalue + "\";"; script += "document.forms[0].submit();"; script += "</script>"; output.Write(script); } } protected override void OnLoad(EventArgs e){ base.OnLoad(e); bool isEnabled = false; if (this.DoesNeedValidation & Page.IsPostBack()){ if (HttpContext.Current.Request[hiddenID] == myvalue) isEnabled = true; JavaScriptDetection.SetValue(isEnabled); } } } }
Line Needed in the Global.asax
void Session_Start(object sender, EventArgs e){ JavaScriptDetection.SetValue(JavaScriptDetection.JavaScriptState.Undefined); }
This strategy is very useful if you write your own JavaScript using your favorite library (mine is jQuery). Try it out, tell me what you think.