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

6

46

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.

Righthand answered 24/7, 2012 at 15:12 Comment(12)
I don't get a notification disabling javascript, using Firefox 13.0.1Chosen
@Sarfraz Er, what? If JS is disabled, it's completely disabled. You can't catch exceptions because no JS code runs at all.Dawkins
@Ali What browser are you using to produce this behavior?Krystinakrystle
@Krystinakrystle as jAndy said, this behavior is no longer there, but it was before, I was late in asking this question, but if there's an answer I would really appreciate.Righthand
@dqhendricks: Ooops didn't have tea when commenting that....Moskowitz
Do I understand it correctly? This detection/notification should happen without a page reload? If that's right: With which method do you disable JS?Vesper
@Vesper Yes without a page reload, in Firefox, I disable Javascript by un-checking the Javascript checkbox in Tools > Options > Content, Javascript/JQuery functions will stop working.Righthand
@AliBassam A continuous refresh iframe would look like this: jsfiddle.net/mBskN/embedded/resultImpel
@Ali: Ah, I see. But when I disable JS in that way, it still runs for all loaded pages (only after reload JS is deactivated).Vesper
related to : #121703Panatella
@karim79 Have you already considered the continous http-refresh postponement approach?Bullpup
@artistoex Some browsers (e.g. Firefox) do not support this. Any change to meta refresh after the page is loaded would result in no effect in such browsers.Impel
I
15

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>
Impel answered 8/2, 2013 at 0:59 Comment(16)
This one "freezes" my Firefox while jsdetect.html is reloaded, but: it works!Vesper
This 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 just like @Vesper said), unless refresh occurs every 10 seconds or so, which isn't an instant detection.Righthand
@Vesper I tried not to overload Firefox with setInterval, but for some reason, Firefox doesn't perform a "meta refresh" if that statement is written through JavaScript (instead of being loaded together with the document).Impel
@Impel Nice solution but it's not that perfect, even with such a small amount of time (40 and 6 msec) I could notice that sometimes the message appears even without JS disabled, and increasing the time would even make it worse, and in order to work, the client has to disable it before it gets the class nojs_hide, which isn't a 100% possibility.Righthand
@AliBassam People would have done this if there is a perfect solution. Given that Facebook has removed this feature, it indicates that there are unresolved issues with such a detection. Fine tuning that delay takes quite some time. You have to adjust both the intervals and CSS delays. The client does not have to disable it before it gets the class nojs_hide since it is a repeating interval. I am not a Facebook engineer but even they couldn't find a perfect solution for this matter. Sometimes we have to accept that we don't live in a perfect world.Impel
@AliBassam See updated answer for a perfect CSS solution. Hopefully the world becomes better because of this.Impel
+1 Now this one is perfect, it worked perfectly, do you think there's any drawbacks/disadvantages with this approach? Anything that might go wrong?Righthand
@AliBassam Maybe the browser compatibility with the use of @keyframes animations?Impel
@AliBassam I have added JavaScript detection of animation support in browsers so that it naturally fallbacks to the standard <noscript> approach for non-supporting browsers.Impel
jsfiddle drives on javascript. Unable to see example with javascript off.Panatella
@MilchePatern The point is to disable javascript after the page is loaded. This is where the instant detection is all about. You can of course copy and paste the code to your local computer and see how it works (no additional codes required).Impel
@Impel You should wrap this code up as a small library and link to it. If you don't - I'll do it :)Jago
@Jago I am glad that you like it. I didn't want to further edit this post because it hit the edit limit and was turned into a community wiki. Now that it's been resolved, we can put this in a library.Impel
@Impel I'm just saying you should start a project on github or something and link it here. The code has potential to get popular. If you don't want to work on it or need help - I can join in.Jago
@Jago Yeah I know, just that I haven't created any libraries before. I am now working on it, but you are definitely welcome to join :)Impel
@Impel my SO profile links to a site with contact information if you need anything - mail me. Let's not make this comment thread any longer :)Jago
P
7

Hrm, I think it depends on the browser. HTML5 supports <noscript> in the HEAD element, so you might try something like this:

<style>
    .noscriptMessage {
         display: none;
     }
</style>
<noscript>
    <style>
        .noscriptMessage {
             display: block
        }
    </style>
</noscript>

<body>
    <div class=".noscriptMessage">Foo bar baz</div>
    ...
</body>

Spec: http://dev.w3.org/html5/markup/noscript.html

From the spec:

Permitted contents: Zero or more of: one link element, or one meta http-equiv=default-style element, or one meta http-equiv=refresh element, or one style element

Edit: hey peeps, SO does the very same! Just try turning off JS now.

Phyla answered 24/7, 2012 at 15:26 Comment(7)
Tis a guess, but based on what the spec says I think it's worth a try.Phyla
btw, I think you want to have some kind of a node, like a <div> within the noscript tag which owns the class noscriptMessageChosen
I always use a meta refresh tag within a noscript tag which redirects to a page for people who have javascript disabled. that is if javascript is required and there is no graceful degradation. this way they don't sit on a page with broken stuff in the mean time.Wideangle
@dqhendricks: but does that satisfy the requirement here too ? Like you just randomly disable JS while beeing on the site already ?Chosen
@Chosen - actually, I though the point here was that the div goes into the body, is hidden, and when the user disables JS the style kicks in and reveals it. I have to leave now, I'll check back here in an hour or so.... Hope that works :)Phyla
@karim79: well yes, it should make no difference anyway. If that noscript tag gets really encountered the second JS gets disabled, it should work either way. But it doesn't look like it works unfortunately.Chosen
@Phyla How do you get this to work? I tested on Chrome, Safari and Firefox but nothing seems to work. And nothing shows on SO either at the moment JavaScript is disabled.Impel
B
2

What about javascript code that continuously postpones a http-equiv=refresh (each time replacing the meta element?) As soon as javascript is turned off, the meta element is no longer replaced and the refresh will eventually take place. This is just a thought, I've no idea if meta element insertion is even possible.

Bullpup answered 24/7, 2012 at 16:19 Comment(1)
While trying to work on this I found something weird, I planned on to postponing the meta refresh, by changing its content continousisly to let's say, 1 second, then change it again to 1 second before that 1 second passes by, so when JS is disabled, the refresh will take place, however, I cannot change the content of meta refresh: #14790565Righthand
D
1

I'd recommend looking into how this is done by HTML5 Boilerplate and Modernizr.

If you look at HTML5 Boilerplate's HTML, on line 7 you'll see the <html> tag is given a class of no-js. Then, when Modernizr's JavaScript runs, the first thing it does is remove the no-js class.

That done, you could apply CSS rules that only display content if the no-js class is present:

#no-script-message {
    display: none;
}
.no-js #no-script-message {
    display: block;
}
Daub answered 24/7, 2012 at 18:22 Comment(4)
How is this related to instant detection?Impel
@Impel Modernizr is designed to be the first script on a page. The first thing the script does is remove the no-js class from the html tag. That way, if JS is disabled, the class will stay put, and if it's enabled, it goes away on page load. This way, you can just put .no-js on the beginning of any CSS selector for elements you want styled different if JavaScript is disabled.Daub
As I'm reading more answers and comments on this thread, I think what you're looking for isn't possible. It'd require a browser to fire some an event when a particular configuration change is made, and then that event would need to be watched by something that can react to it. The only thing in a browser that can react dynamically to an event is JavaScript, so if the user just turned it off, there'd be no way to respond to that event.Daub
What about my answer that uses CSS animation to "detect" if JavaScript is turned off?Impel
G
0

Expanding upon @JoshMock's answer, here is a simple approach (via Paul Irish) to detect if the client has JS enabled:

HTML

<html class="no-js">
<head>
  <script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>

This should be compatible with all browsers and is quite fast. Then you can hide/show elements in your css with .js and .no-js classes.

If you are doing any other feature detection, I would suggest using Modernizr with the html class="no-js" markup (modernizr will automatically add the js classes for you, along with css3 detection).

Gadwall answered 7/2, 2013 at 20:7 Comment(11)
Correct me if I'm wrong, here's what I understood: At the beginning, the <html> is given a class no-js, when page loads, that class is changed to js, and in CSS, the message will show when the class is no-js. So when I load the page with JS disabled, the class won't be changed, so the message will be shown. If this is the case, then what about instantly detecting when the client disables JS?Righthand
I do not think that there is a more "instant" way of detecting this. You cannot detect for the absence of javascript without javascript, and there is no cross-browser method of doing this either (at least that I know of). The small line of javascript is going to execute faster before any element on the page. If you are trying to detect if the client has disabled JS after the page has loaded (which is an edge case at best, then @karim79's no-script solution is best (for browsers that support it)Gadwall
@AliBassam, Looking at how you are ignoring good answers, I would say - Stop all this madness and start building a new Web, with less bullshit, and more JavaScriptNitro
@OmShankar The OP has always been asking for a way to instantly detect the absence of JavaScript. If an answer doesn't address the question directly, no matter how good its content is, is still irrelevant.Impel
@NickTomlin You can use something other than JavaScript to detect the absence of JavaScript. And I haven't come across a browser that supports karim79's solution (it only works onload, not after it).Impel
@Antony, the question is irrelevant in current browser and web development scope. There should not be a need of such a scenario, if it is, then you are going in the wrong direction. Its not Web. Anyways, that's why I am writing a comment and not an answer. I am actually commenting - less bullshit and more JS ! Please !Nitro
@Antony, create an infinite CSS animation and make firefox suck, refresh iframe urls, modify dom illogically... come on! At least 1000 people disagree, thats why I saw this message above - This question has not received enough attention. :)Nitro
@OmShankar It would be nice if you can come up with a better and cleaner solution for this. This question has not received enough attention and we are stuck with shitty tricks and hacks.Impel
@Antony, you don't get the point. I don't have a solution for this, and don't see a need. Neither of my friend web devs do. Rather, I am recommending people to stay away from spending time in thisNitro
@OmShankar I haven't ignored any good solution, I have tested what users have provided, when I found something wrong I commented, when I found something good I commented and upvoted, I am not counting on myself to define if an answer is good or not because I do not consider myself a web developer God, I'm counting on users feedbacks, I activated this bounty because this question had many upvotes and favored many times but no real solution was found, please stop flooding with your pointless comments, try to find a solution or you can downvote and ignore this question, Thank you.Righthand
@AliBassam, things are going wrong here. The question seems like something and is upvoted, but coming to answers and your responses, seems you want something which is not in scope of "good web development". So I want to save the world by refraining them from this idea itself. Simple :)Nitro
P
-3

Actually, it is easier to detect if java-script is supported by the browser than the opposite.

Of course, this is in the case of 'a site instantly detect javascript'. Witch is the very first http-request <--> response from the browser to the server. You just 'cannot'. You would have to send another request to the server after determining browser capabilities.

Now, there is no way of checking if JavaScript is enabled from the server-side on the first request. So, if JavaScript is disabled, you have to do a postback, or redirect to a non JavaScript page, using what some other suggested (witch is not valid, but seems to work):

<head>
    <noscript><meta http-equiv="refresh" content="0; url=whatyouwant.html"></noscript>
...
</head>

There are some 'browser capabilities' and browser 'plugins' that can be get with http request, so you would need a good 'server-side' script to meet your goal.

See browserhawk or quirksmode for some infos on a javascript to detect browser.

Also, there is a 'protected' question aboout how-to-detect-if-javascript-is-disabled

Panatella answered 7/2, 2013 at 16:42 Comment(3)
@Ali Bassam (& and others) for sure if you modify your question, this answer will look irrelevant and down-voted.Panatella
The OP has been asking for a way to instantly detect the absence of JavaScript. This idea is never changed.Impel
@Impel you're right, the idea never changed. Still, there is no way 'yet' to detect 'instantly' browser capabilities.Panatella

© 2022 - 2024 — McMap. All rights reserved.