今天早上有个帖子问有多少人禁用JavaScript。然后我开始想知道可以使用什么技术来确定用户是否禁用了它。
有人知道一些简单的方法来检测JavaScript是否被禁用吗?我的意图是给一个警告,如果浏览器没有启用JS,站点将无法正常运行。
最终,我想把它们重定向到能够在没有JS的情况下工作的内容,但我需要这个检测作为一个占位符来开始。
今天早上有个帖子问有多少人禁用JavaScript。然后我开始想知道可以使用什么技术来确定用户是否禁用了它。
有人知道一些简单的方法来检测JavaScript是否被禁用吗?我的意图是给一个警告,如果浏览器没有启用JS,站点将无法正常运行。
最终,我想把它们重定向到能够在没有JS的情况下工作的内容,但我需要这个检测作为一个占位符来开始。
当前回答
Why don't you just put a hijacked onClick() event handler that will fire only when JS is enabled, and use this to append a parameter (js=true) to the clicked/selected URL (you could also detect a drop down list and change the value- of add a hidden form field). So now when the server sees this parameter (js=true) it knows that JS is enabled and then do your fancy logic server-side. The down side to this is that the first time a users comes to your site, bookmark, URL, search engine generated URL- you will need to detect that this is a new user so don't look for the NVP appended into the URL, and the server would have to wait for the next click to determine the user is JS enabled/disabled. Also, another downside is that the URL will end up on the browser URL and if this user then bookmarks this URL it will have the js=true NVP, even if the user does not have JS enabled, though on the next click the server would be wise to knowing whether the user still had JS enabled or not. Sigh.. this is fun...
其他回答
这里是转折! 可能有客户端浏览器启用了Javascript,并且使用JS兼容的浏览器。但是不管出于什么原因Javascript在浏览器中不能工作(比如:防火墙设置)。据统计,这种情况每93个场景中就会发生1个。所以服务器检测到客户端有能力执行Javascript,但实际上并没有!
作为解决方案,我建议我们在客户端站点设置一个cookie,然后从服务器读取它。如果cookie设置好了,JS就可以正常工作。有什么想法吗?
一个常见的解决方案是将元标记与noscript结合起来刷新页面,并在JavaScript被禁用时通知服务器,如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<noscript>
<meta http-equiv="refresh" content="0; /?javascript=false">
</noscript>
<meta charset="UTF-8"/>
<title></title>
</head>
</html>
在上面的例子中,当JavaScript被禁用时,浏览器将在0秒内重定向到网站的主页。此外,它还会向服务器发送参数javascript=false。
然后,服务器端脚本(如node.js或PHP)可以解析该参数,并知道JavaScript已禁用。然后,它可以向客户端发送一个特殊的非javascript版本的网站。
下面是一个PHP脚本,它可以在生成任何输出之前包含一次。它不是完美的,但在大多数情况下,它工作得足够好,以避免交付客户端不会使用的内容或代码。标题注释解释了它是如何工作的。
<?php
/*****************************************************************************
* JAVASCRIPT DETECTION *
*****************************************************************************/
// Progressive enhancement and graceful degradation are not sufficient if we
// want to avoid sending HTML or JavaScript code that won't be useful on the
// client side. A normal HTTP request will not include any explicit indicator
// that JavaScript is enabled in the client. So a "preflight response" is
// needed to prompt the client to provide an indicator in a follow-up request.
// Once the state of JavaScript availability has been received the state of
// data received in the original request must be restored before proceding.
// To the user, this handshake should be as invisible as possible.
//
// The most convenient place to store the original data is in a PHP session.
// The PHP session extension will try to use a cookie to pass the session ID
// but if cookies are not enabled it will insert it into the query string.
// This violates our preference for invisibility. When Javascript is not
// enabled the only way to effect a client side redirect is with a "meta"
// element with its "http-equiv" attribute set to "refresh". In this case
// modifying the URL is the only way to pass the session ID back.
//
// But when cookies are disabled and JavaScript is enabled then a client side
// redirect can be effected by setting the "window.onload" method to a function
// which submits a form. The form has a "method" attribute of "post" and an
// "action" attribute set to the original URL. The form contains two hidden
// input elements, one in which the session ID is stored and one in which the
// state of JavaScript availability is stored. Both values are thereby passed
// back to the server in a POST request while the URL remains unchanged. The
// follow-up request will be a POST even if the original request was a GET, but
// since the original request data is restored, the containing script ought to
// process the request as though it were a GET.
// In order to ensure that the constant SID is defined as the caller of this
// script would expect, call session_start if it hasn't already been called.
$session = isset($_SESSION);
if (!$session) session_start();
// Use a separate session for Javascript detection. Save the caller's session
// name and ID. If this is the followup request then close the caller's
// session and reopen the Javascript detection session. Otherwise, generate a
// new session ID, close the caller's session and create a new session for
// Javascript detection.
$session_name = session_name();
$session_id = session_id();
session_write_close();
session_name('JS_DETECT');
if (isset($_COOKIE['JS_DETECT'])) {
session_id($_COOKIE['JS_DETECT']);
} elseif (isset($_REQUEST['JS_DETECT'])) {
session_id($_REQUEST['JS_DETECT']);
} else {
session_id(sha1(mt_rand()));
}
session_start();
if (isset($_SESSION['_SERVER'])) {
// Preflight response already sent.
// Store the JavaScript availability status in a constant.
define('JS_ENABLED', 0+$_REQUEST['JS_ENABLED']);
// Store the cookie availability status in a constant.
define('COOKIES_ENABLED', isset($_COOKIE['JS_DETECT']));
// Expire the cookies if they exist.
setcookie('JS_DETECT', 0, time()-3600);
setcookie('JS_ENABLED', 0, time()-3600);
// Restore the original request data.
$_GET = $_SESSION['_GET'];
$_POST = $_SESSION['_POST'];
$_FILES = $_SESSION['_FILES'];
$_COOKIE = $_SESSION['_COOKIE'];
$_SERVER = $_SESSION['_SERVER'];
$_REQUEST = $_SESSION['_REQUEST'];
// Ensure that uploaded files will be deleted if they are not moved or renamed.
function unlink_uploaded_files () {
foreach (array_keys($_FILES) as $k)
if (file_exists($_FILES[$k]['tmp_name']))
unlink($_FILES[$k]['tmp_name']);
}
register_shutdown_function('unlink_uploaded_files');
// Reinitialize the superglobal.
$_SESSION = array();
// Destroy the Javascript detection session.
session_destroy();
// Reopen the caller's session.
session_name($session_name);
session_id($session_id);
if ($session) session_start();
unset($session, $session_name, $session_id, $tmp_name);
// Complete the request.
} else {
// Preflight response not sent so send it.
// To cover the case where cookies are enabled but JavaScript is disabled,
// initialize the cookie to indicate that JavaScript is disabled.
setcookie('JS_ENABLED', 0);
// Prepare the client side redirect used when JavaScript is disabled.
$content = '0; url='.$_SERVER['REQUEST_URI'];
if (!$_GET['JS_DETECT']) {
$content .= empty($_SERVER['QUERY_STRING']) ? '?' : '&';
$content .= 'JS_DETECT='.session_id();
}
// Remove request data which should only be used here.
unset($_GET['JS_DETECT'],$_GET['JS_ENABLED'],
$_POST['JS_DETECT'],$_POST['JS_ENABLED'],
$_COOKIE['JS_DETECT'],$_COOKIE['JS_ENABLED'],
$_REQUEST['JS_DETECT'],$_REQUEST['JS_ENABLED']);
// Save all remaining request data in session data.
$_SESSION['_GET'] = $_GET;
$_SESSION['_POST'] = $_POST;
$_SESSION['_FILES'] = $_FILES;
$_SESSION['_COOKIE'] = $_COOKIE;
$_SESSION['_SERVER'] = $_SERVER;
$_SESSION['_REQUEST'] = $_REQUEST;
// Rename any uploaded files so they won't be deleted by PHP. When using
// a clustered web server, upload_tmp_dir must point to shared storage.
foreach (array_keys($_FILES) as $k) {
$tmp_name = $_FILES[$k]['tmp_name'].'x';
if (move_uploaded_file($_FILES[$k]['tmp_name'], $tmp_name))
$_SESSION['_FILES'][$k]['tmp_name'] = $tmp_name;
}
// Have the client inform the server as to the status of Javascript.
?>
<!DOCTYPE html>
<html>
<head>
<script>
document.cookie = 'JS_ENABLED=1';
// location.reload causes a confirm box in FireFox
// if (document.cookie) { location.reload(true); }
if (document.cookie) { location.href = location; }
</script>
<meta http-equiv="refresh" content="<?=$content?>" />
</head>
<body>
<form id="formid" method="post" action="" >
<input type="hidden" name="<?=$session_name?>" value="<?=$session_id?>" />
<input type="hidden" name="JS_DETECT" value="<?=session_id()?>" />
<input type="hidden" name="JS_ENABLED" value="1" />
</form>
<script>
document.getElementById('formid').submit();
</script>
</body>
</html>
<?php
exit;
}
?>
当浏览器中没有启用js时,<noscript>标记中的代码将被执行。 我们可以使用noscript标签来显示msg来打开JS,如下所示。
<noscript>
<h1 style="text-align: center;">
To view this page properly, please
enable JavaScript and reload the page
</h1>
</noscript>
同时保持我们的网站内容在身体隐藏。如下
<body>
<div id="main_body" style="display: none;">
website content.
</div>
</body>
现在如果JS是打开的,你可以让main_body中的内容可见,如下所示
<script type="text/javascript">
document.getElementById("main_body").style.display="block";
</script>
只是有点难,但是(发型师给了我灵感)
CSS:
.pagecontainer {
display: none;
}
JS:
function load() {
document.getElementById('noscriptmsg').style.display = "none";
document.getElementById('load').style.display = "block";
/* rest of js*/
}
HTML:
<body onload="load();">
<div class="pagecontainer" id="load">
Page loading....
</div>
<div id="noscriptmsg">
You don't have javascript enabled. Good luck with that.
</div>
</body>
在任何情况下都是可行的,对吧? 即使noscript标签不受支持(只需要一些CSS) 有人知道非CSS的解决方案吗?