一、一般思路
严格来讲,右键菜单应该叫上下文菜单,在html5中也新定义了这个contextmenu全局属性。
它的语法是这样的:
contextmenu
属性规定元素的上下文菜单。当用户右键点击元素时,会出现上下文菜单。contextmenu
属性的值是要打开的<menu>
元素的 id。
在这里,我注意到浏览器支持问题:
!!!但是!
在Firefox中并没有出现预想中的结果!
然后我发现下面这样可以实现:
所以这里要注意一下,
①w3cschool上
<menu>
的子标签用的是<command>
,是有问题的;菜鸟教程上用的是<menuitem>
,亲测可行。②w3cschool上没有给
<menu>
加一个type属性,必须要加上type=”context”才能成功实现。
更细致的关于menu和menuitem实现上下文菜单可以参考博文《利用HTML 5中的Menu和Menuitem元素快速创建菜单》
可能大家也发现了,这个contextmenu属性只能在原有的上下文菜单上添加,而不能对原有的上下文菜单项进行删除等操作,这样是它的局限性。这时,就需要我们自己通过js来模拟右键点击出现上下文菜单。
写过一段时间JS的都知道,我们实现这个上下文菜单大概这个思路:
写个ul列表(隐藏掉) -> 监听鼠标右键事件 -> 将ul列表显示出来
但是,实现的时候,还需要注意几个细节,于是我将这个粗糙的思路细化了一下:
(文中js代码都是基于jQuery的)
1.1 阻止浏览器默认右键菜单(上下文菜单)
|
1.2 定义一个ul列表
|
这里要注意列表的放置位置,跟上下文菜单作用的区域相关。
1.3 监听鼠标右键点击事件
这里是根据事件对象的button值来判断的,比如mousedown的事件对象:
由于click事件和mousedown事件很像,在这里将两者做一下比较:
鼠标事件 | button值 | 事件描述 |
---|---|---|
click | 0 | 单击鼠标左键 |
click | 1 | 单击鼠标中键 |
mousedown | 0 | 鼠标左键被按下 |
mousedown | 1 | 鼠标中键被按下 |
mousedown | 2 | 鼠标右键被按下 |
click事件只会在单击鼠标左键和中键时触发,单击右键时不会触发
给ul列表定位及显示
之前我们提到列表的放置位置,就是为了更准确的给它定位。一般上下文菜单是显示在鼠标稍微右下角的地方,所有首先要定位当前鼠标的坐标。
参数 | 说明 | 兼容性 |
---|---|---|
clientX、clientY | 触发点相对浏览器可视区域左上角距离,不随页面滚动而改变 | 所有浏览器均支持 |
pageX、pageY | 触发点相对文档区域左上角距离,会随着页面滚动而改变 | IE6/7/8不支持 |
offsetX、offsetY | 触发点相对被触发dom的左上角距离,不过左上角基准点在不同浏览器中有区别,其中在IE中以内容区左上角为基准点不包括边框,如果触发点在边框上会返回负值,而chrome中以边框左上角为基准点。 | IE所有版本,chrome,Safari均完美支持,Firefox不支持 |
layerX、layerY | 触发点相对被触发dom左上角的距离,数值与offsetX/Y相同,这个变量就是firefox用来替代offsetX/Y的,基准点为边框左上角,但是有个条件就是,被触发的dom需要设置为position:relative或者position:absolute,否则会返回相对html文档区域左上角的距离 | IE6/7/8不支持,opera不支持,IE9/10和Chrome、Safari均支持 |
screenX、screenY | 触发点相对显示器屏幕左上角的距离,不随页面滚动而改变 | 所有浏览器均支持 |
选择给鼠标定位的参数,那么就选择相应的方式给ul列表定位。
个人推荐使用pageX和pageY,因为我们最后给ul列表定位时,会用到position:absolute
。绝对定位是相对于 static定位以外的第一个父元素进行定位。如果两者都是body定位的话,不容易出现定位失误。然后再display:block
。
多定义一个事件:鼠标左键点击页面,ul列表
display:none
1.4 简单实现
代码:
效果:
二、插件
事实上,大神早已为我们打造好了“神器”,请戳张鑫旭的
《jQuery smartMenu右键自定义上下文菜单插件》