How can a site instantly detect that javascript has been disabled?

Ali Bassam picture Ali Bassam · Jul 24, 2012 · Viewed 8.1k times · Source

Normally, when a page is loaded, and the browser has Javascript disabled, we use the <noscript> tag to write something like a warning and tell the client to enable Javascript. However, Facebook, even after you load the page with JS enabled, the moment it's disabled you get a notification. How can I do something like this?

UPDATE : This mechanism is no longer available in Facebook, but it was before, I was too late in asking this question, but if any answer is found, I would really appreciate it.

What I have tried

I thought about having a segment inside my page which keeps checking if Javascript is disabled, if yes, show the contents of <noscript>.

To Achieve this, I created a page CheckJS.html.

<!DOCTYPE html>

<html>
<head>
    <meta http-equiv="refresh" content="0">
</head>
<body>
    <noscript>
       JS is disabled!
    </noscript>
</body>
</html>

This page will keep on refreshing, when JS is disabled, JS is disabled! will appear.

To add this page inside my original page. I tried the following:

1- .load()

I used JQuery to .load('CheckJS.html') inside a div. However, it seems that .load() only loads the contents of the <body> of CheckJS.html. Means the <head> element and what's inside it will not be loaded inside the div.

2- iframe

After some searching, I found that the only possible way to load a FULL html page including <head> is to use an <iframe>.

<iframe src="CheckJS.html"></iframe>

However, the <meta http-equiv="refresh" content="0"> of CheckJS.html affects the parent page, the original page itself started refreshing.

If we are able to use this <iframe> without forcing the original page to refresh, then this could be a solution, but even if this solution is found, I feel its more of a trick rather than a real solution.


UPDATE

Antony 's answer proved that I was wrong about that the iframe refreshes the original page, the browser shows that its refreshing but actually its not, if this is it, then Javascript can be avoided, the CheckJS.html that I provided does the job, and even better, the <noscript> will be hidden when JS is re-enabled. Still this whole iframe approach isn't so user friendly (could freeze the browser), unless refresh occurs every 10 seconds or so, which isn't an instant detection.

Answer

Antony picture Antony · Feb 8, 2013

CSS Solution

See DEMO. Also available as a JS library.

Stop the CSS animation by continuously replacing the element with JavaScript. Once JavaScript is disabled, the CSS animation kicks in and displays a message.

@keyframes Browser compatibility: Chrome, Firefox 5.0+, IE 10+, Opera 12+, Safari 4.0+

<style>
.nojs_init { 
position: relative;
animation:nojs-animation 0.2s step-end;
-moz-animation:nojs-animation 0.2s step-end; /* Firefox */
-webkit-animation:nojs-animation 0.2s step-end; /* Safari and Chrome */
-o-animation:nojs-animation 0.2s step-end; /* Opera */
}

@keyframes nojs-animation
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}

@-moz-keyframes nojs-animation /* Firefox */
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}

@-webkit-keyframes nojs-animation /* Safari and Chrome */
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}

@-o-keyframes nojs-animation /* Opera */
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}
</style>
<body>
<div id="content"></div>
<div id="nojs" class="nojs_init"><noscript>JavaScript is <span style="font-weight:bold;">disabled</span>.</noscript></div>
</body>
<script>
document.getElementById("content").innerHTML = 'JavaScript is <span style="font-weight:bold;">enabled</span>. Try disabling JavaScript now.';

var elm = document.getElementById("nojs"),
    animation = false,
    animationstring = 'animation',
    keyframeprefix = '',
    domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
    pfx  = '';
 
if( elm.style.animationName ) { animation = true; }    
 
if( animation === false ) {
  for( var i = 0; i < domPrefixes.length; i++ ) {
    if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
      pfx = domPrefixes[ i ];
      animationstring = pfx + 'Animation';
      keyframeprefix = '-' + pfx.toLowerCase() + '-';
      animation = true;
      break;
    }
  }
}

// Continuously replace element
function jsdetect() {
    var elm = document.getElementById("nojs");
    var newone = elm.cloneNode(true);
    elm.parentNode.replaceChild(newone, elm);
}

// Only apply to browsers that support animation
if (animation) {
    elm.innerHTML = 'JavaScript is <span style="font-weight:bold;">disabled</span>.';
    setInterval(jsdetect, 0);
}
</script>