本文详细解析了使用JavaScript和jQuery屏蔽网页鼠标右键菜单及禁止文本选择的多种实现方式。内容涵盖从粗暴的全局禁用到基于HTML标签白名单的精细化控制,重点介绍了如何通过判断事件目标元素来保留输入框等控件的正常交互,同时提供完整的jQuery代码示例以解决兼容性问题。
引言:网页右键屏蔽的背景与必要性
早期接触动态HTML与JavaScript时,常遇到用于屏蔽鼠标右键的代码。这类脚本最初多用于防止未经授权复制网页内容,但后续实践表明,这种做法往往损害用户体验,且存在多种破解手段,例如已有文章专门讲解如何解除网页禁止复制的限制。
尽管限制右键和复制并非明智之举,但在网页应用(Web App)技术日益成熟的背景下,网页与桌面应用的界限逐渐模糊。许多桌面程序或手机应用实际上由HTML5结合JavaScript构建。在此类应用中,网页右键选择文字及弹出菜单往往显得多余,因此限制右键操作具有实际必要性。
下文介绍的代码可能仅涉及某一特定方面,但相信读者能够举一反三,灵活应用于实际开发中。
基础版:限制选择复制或禁止鼠标右键
一、基础版:限制选择复制或禁止鼠标右键
首先探讨如何直接限制用户复制网页文字。常规思路是禁用用户的特定操作,如鼠标右键、文本选择和复制等。这些操作对应特定的脚本事件,只需为这些事件绑定返回false的方法,即可“拦截”该操作。以下是一段较为粗暴的禁止复制脚本代码示例:
代码如下:
window.onload = function() {
with(document.body) {
oncontextmenu=function(){return false}
ondragstart=function(){return false}
onselectstart=function(){return false}
onbeforecopy=function(){return false}
onselect=function(){document.selection.empty()}
oncopy=function(){document.selection.empty()}
}
}该方法被称为“粗暴版”,原因在于全局禁用右键后,网页上所有控件均无法右击或选择,页面仿佛变成静态图片。虽然这看似无关紧要,但对于input、textarea等字符输入控件而言,限制右键及选择复制功能将严重影响用户正常使用。
基于HTML标签元素的合理判断
二、基于HTML标签元素的合理判断
如何判断当前处理层所在的元素标签,即获取鼠标当前所在的HTML Tag?以oncontextmenu为例,传入的函数实际上有一个被忽略的参数,完整写法应为document.body.oncontextmenu=function(e){},其中e为JavaScript中的Event事件对象,在IE中可能通过window.event获取。利用该事件对象可获取触发事件时鼠标所在的HTML Tag,进而判断是否忽略处理特定元素标签。以下提供一个相关函数:
代码如下:
var isTagName = function(e, whitelists) {
e = e || window.event;
var target = e.target || e.srcElement;
Array.prototype.contains = function(elem)
{
for (var i in this)
{
if (this[i].toString().toUpperCase() == elem.toString().toUpperCase()) return true;
}
return false;
}
if (whitelists && !whitelists.contains(target.tagName)) {
return false;
}
return true;
};
上述代码中,e为事件对象event,target为事件引用的元素对象,两者均采用了兼容IE的写法(具体可参考《How can I make event.srcElement work in Firefox and what does it mean?》)。whitelists为白名单HTML元素标签名,例如['INPUT', 'TEXTAREA'],表示将输入文本框input和textarea纳入判断。若当前事件元素属于白名单,则返回true,从而通过以下代码选择性屏蔽鼠标右键:
代码如下:
document.body.oncontextmenu=function(e){
return isTagName(e, ['A', 'TEXTAREA']);
}
jQuery版选择性屏蔽禁止文本选择
三、jQuery版选择性屏蔽禁止文本选择
对于其他操作,同样可以选择性屏蔽。在jQuery支持的环境中,参考StackOverflow上的文章《How to disable text selection using jQuery?》,虽然该文主要讲解禁止选择,但可借鉴其思路。具体代码如下:
代码如下:
(function($){
$.fn.ctrlCmd = function(key) {
var allowDefault = true;
if (!$.isArray(key)) {
key = [key];
}
return this.keydown(function(e) {
for (var i = 0, l = key.length; i < l; i++) {
if(e.keyCode === key[i].toUpperCase().charCodeAt(0) && e.metaKey) {
allowDefault = false;
}
};
return allowDefault;
});
};
$.fn.disableSelection = function() {
this.ctrlCmd(['a', 'c']);
return this.attr('unselectable', 'on')
.css({'-moz-user-select':'-moz-none',
'-moz-user-select':'none',
'-o-user-select':'none',
'-khtml-user-select':'none',
'-webkit-user-select':'none',
'-ms-user-select':'none',
'user-select':'none'})
.bind('selectstart', false);
};
})(jQuery);使用时可采取以下代码:
代码如下:
$(':not(input,select,textarea)').disableSelection();
此代码排除了input、select、textarea元素的禁止选择功能。其技巧在于除了使用selectstart外,还为相关元素添加了特定浏览器支持的CSS属性,从而基本实现大多数浏览器的兼容。同时,该代码还屏蔽了键盘按键选择Ctrl+A和Ctrl+C,体现了作者周到的考虑。
进一步完善:屏蔽鼠标点击操作
四、进一步完善:屏蔽鼠标点击操作
在测试这段代码时,发现点击除input、select、textarea外的元素时会全选页面。原文作者给出一个简单方法,即在代码后附加.on('mousedown', false),以屏蔽鼠标单击,使用代码变为:
代码如下:
$(':not(input,select,textarea)').disableSelection().on('mousedown', false);然而,问题随之出现:应用上述代码后,input、select、textarea元素也变得异常,似乎屏蔽mousedown的特性被应用到了所有元素上。转换思路,结合前文提出的方案,通过判断event对象来实现选择性屏蔽,修正后的代码如下:
代码如下:
$(':not(input,select,textarea)').disableSelection().on('mousedown', function(e) {
var event = $.event.fix(e);
var elem = event.target || e.srcElement;
if (elem.tagName.toUpperCase() != 'TEXTAREA' && elem.tagName.toUpperCase() != 'INPUT') {
e.preventDefault();
return false;
}
return true;
});这样,textarea和input便不再受mousedown限制。将这段代码抽出为函数:
代码如下:
function jQuery_isTagName(e, whitelists) {
e = $.event.fix(e);
var target = e.target || e.srcElement;
if (whitelists && $.inArray(target.tagName.toString().toUpperCase(), whitelists) == -1) {
return false;
}
return true;
}
$(':not(input,select,textarea)').disableSelection().on('mousedown', function(e) {
if (!jQuery_isTagName(e, ['INPUT', 'TEXTAREA'])) {
e.preventDefault();
return false;
}
return true;
});
jQuery版选择性屏蔽禁止鼠标右键
五、jQuery版选择性屏蔽禁止鼠标右键
对于右键菜单,可按以下方式处理:
代码如下:
$(document).bind("contextmenu",function(e){
if (!jQuery_isTagName(e, ['INPUT', 'TEXTAREA'])) {
e.preventDefault();
return false;
}
return true;
});