new
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# contextMenu
|
||||
自由定制页面元素的右键菜单。
|
||||
|
||||

|
||||
|
||||
> 是的同类的插件很多,作者造轮子是因为当初寻找右键菜单插件的时候,找了几个都有bug,要么经不起环境的考验,只能跑通demo。如果你也在寻找一款右键菜单插件,不如试试这一款,应该不会让你失望。
|
||||
|
||||
## 最新版本
|
||||
v2.2.5
|
||||
## 原理
|
||||
该插件通过指定的参数,渲染出一个漂亮的右键菜单,并绑定菜单项点击事件。
|
||||
|
||||
需要的参数有:
|
||||
|
||||
1. 右键事件e。指定一个事件e,它可能是通过原生js、jq,甚至vue捕捉的;该插件将获取点击的位置,并阻止事件冒泡,屏蔽默认的右键菜单。
|
||||
2. 菜单描述数组menu。menu数组决定了你想渲染出什么样的菜单。
|
||||
|
||||
## 特色
|
||||
|
||||
* 侵入性小,这个插件几乎不会影响全局,除了ContextMenu全局变量。
|
||||
* 兼容性好,在各个屏幕尺寸和有无滚动条的场景都有不错的渲染效果。
|
||||
* 支持多层嵌套的DOM触发的事件,以最里层为准(详见demo)。
|
||||
* 支持二级菜单。
|
||||
|
||||
## 准备
|
||||
|
||||
1. 下载源码(并点赞)
|
||||
2. 引入 jquery
|
||||
3. 引入 contextMenu.css
|
||||
4. 引入 contextMenu.js
|
||||
|
||||
## 典型用法
|
||||
|
||||
~~~js
|
||||
$('body').contextmenu(function (e) {
|
||||
var menu=[
|
||||
'menu1', //合理的html或纯文字
|
||||
'menu2',
|
||||
'|', //分隔符
|
||||
[
|
||||
'click me', //title
|
||||
function (dom) {alert('Hi')} // 点击菜单项的回调
|
||||
],
|
||||
];
|
||||
ContextMenu.render(e,menu,this); //开始渲染
|
||||
});
|
||||
~~~
|
||||
|
||||
## API
|
||||
`ContextMenu.render(e,menu,param,theme)`
|
||||
|
||||
**e**:点击事件对象,如`$('body').contextmenu(function (e){})`。
|
||||
|
||||
**menu**:
|
||||
|
||||
menu为`true`代表禁用系统默认菜单,但是不渲染自定义菜单;
|
||||
|
||||
menu为数组表示渲染自定义右键菜单;
|
||||
~~~js
|
||||
var menu=[
|
||||
'文字1', //纯文字或html将直接被渲染,做为一个提示性菜单项
|
||||
'文字2',
|
||||
'|', //简单的一个分隔符
|
||||
['功能1',function(param){alert("功能1点击")}], //这种格式说明这个菜单项可以被点击并产生回调
|
||||
[
|
||||
'子菜单',[
|
||||
'文字3',
|
||||
'文字4',
|
||||
'|',
|
||||
['功能2',function(param){alert("功能2点击")}],
|
||||
]
|
||||
] //声明一个子菜单,子菜单内部的声明格式和父级一样
|
||||
]
|
||||
~~~
|
||||
|
||||
**param**:菜单点击回调的第一个参数
|
||||
|
||||
**theme**:主题(目前可选主题"light")
|
||||
|
||||
## 其他
|
||||
注意:为了获得正确的屏幕尺寸,添加了一个`html,body:{height:100%}`的样式,请确保该样式生效不被覆盖。
|
||||
|
||||
## 更多项目
|
||||
[Yuri2'Projects](https://github.com/yuri2peter/)
|
||||
|
||||
## TOOD
|
||||
|
||||
* 右键菜单,二级垂直方向有可能溢出
|
||||
|
||||
## 更新记录
|
||||
|
||||
* v2.2.5 修复文字溢出(title提示)和子菜单底部溢出
|
||||
* v2.2.3 优化css
|
||||
* v2.2.2 新增第三个参数[bool] disable 临时禁用菜单点击功能 `['功能2',function(param){alert("功能2点击")},true]`
|
||||
* v2.2.1 优化css
|
||||
* v2.2.0 新增主题切换功能
|
||||
* v2.1.1 修复了二级菜单溢出屏幕的问题,更好的兼容性
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.yuri2-context-menu {
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: fixed;
|
||||
width: 150px;
|
||||
height: auto;
|
||||
background-color: rgb(61, 61, 61);
|
||||
display: block;
|
||||
/*border-radius: 5px;*/
|
||||
z-index: 99999999;
|
||||
color: white;
|
||||
/*overflow: hidden;*/
|
||||
}
|
||||
.yuri2-context-menu.sub {
|
||||
left: 98%;
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
.yuri2-context-menu.sub.left {
|
||||
left: auto;
|
||||
right: 98%;
|
||||
}
|
||||
.yuri2-context-menu ul li:hover .yuri2-context-menu.sub {
|
||||
display: block;
|
||||
}
|
||||
.yuri2-context-menu ul.left .yuri2-context-menu.sub{
|
||||
left: -100%;
|
||||
}
|
||||
.yuri2-context-menu ul {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
box-shadow: 0 0 16px rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
|
||||
.yuri2-context-menu ul li {
|
||||
transition: background-color 0.5s;
|
||||
cursor: default;
|
||||
padding: 0px 1em;
|
||||
list-style: none;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-size: 10px;
|
||||
/*overflow: hidden;*/
|
||||
position: relative;
|
||||
}
|
||||
.yuri2-context-menu ul li div.title{
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
float: left;
|
||||
word-break: break-all;
|
||||
}
|
||||
.yuri2-context-menu ul li div.title.disable {
|
||||
color: darkgrey;
|
||||
}
|
||||
.yuri2-context-menu ul li.sub:after {
|
||||
content: ">";
|
||||
float: right;
|
||||
transform: scale3d(0.5,1.5,1);
|
||||
position: relative;
|
||||
}
|
||||
.yuri2-context-menu ul li:hover {
|
||||
background-color: #636363;
|
||||
}
|
||||
|
||||
.yuri2-context-menu ul li a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
height: 100%;
|
||||
color: #333;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.yuri2-context-menu ul hr {
|
||||
margin: 0;
|
||||
height: 0;
|
||||
border: 0;
|
||||
border-bottom: rgba(132, 132, 132, 0.47) 1px solid;
|
||||
border-top: none
|
||||
}
|
||||
|
||||
/*浅色主题*/
|
||||
.yuri2-context-menu.light {background-color: #e0e0e0;border-color: #535353;color: #333333;}
|
||||
.yuri2-context-menu.light ul li:hover {background-color: #707070;color: #ffffff;}
|
||||
.yuri2-context-menu.light ul hr{border-color: #535353;}
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* contextMenu v2.2.4
|
||||
* @author Yuri2(yuri2peter@qq.com)
|
||||
* @link https://github.com/yuri2peter/contextMenu
|
||||
* Enjoy! (●'◡'●)
|
||||
* 基于jq的右键菜单(动态绑定)
|
||||
* @author Yuri2
|
||||
*/
|
||||
window.ContextMenu={
|
||||
_className:'yuri2-context-menu',
|
||||
_stopProp:function (e) {
|
||||
if (e.cancelable) {
|
||||
// 判断默认行为是否已经被禁用
|
||||
if (!e.defaultPrevented) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
},
|
||||
_getMainContent:function(text){
|
||||
return text.replace(/<\/?.+?>/g,"");
|
||||
},
|
||||
render:function (e, menu, trigger,theme) {
|
||||
theme||(theme='');
|
||||
var x=e.clientX,y=e.clientY;
|
||||
this._stopProp(e);
|
||||
this._removeContextMenu();
|
||||
if(menu===true){return;}
|
||||
if(typeof menu === 'object' && menu.length===0){menu=[['...']]}
|
||||
var dom = $("<div class='"+ContextMenu._className+" "+theme+"'><ul></ul></div>");
|
||||
$('body').append(dom);
|
||||
var ul=dom.find('ul');
|
||||
if(x+150>document.body.clientWidth){x-=150;ul.addClass('left')}
|
||||
menu.forEach(function (item) {
|
||||
if(item==='|'){
|
||||
ul.append($('<hr/>'));
|
||||
}
|
||||
else if(typeof(item)==='string'){
|
||||
ul.append($('<li><div class="title" title="'+ContextMenu._getMainContent(item)+'">'+item+'</div></li>'));
|
||||
}
|
||||
else if(typeof(item)==='object'){
|
||||
var sub=$('<li><div class="title '+(item[2]===true?'disable':'')+'" title="'+ContextMenu._getMainContent(item[0])+'">'+item[0]+'</div></li>');
|
||||
ul.append(sub);
|
||||
if(typeof(item[1])==='object'){
|
||||
var subMenu=$("<div class='sub "+ContextMenu._className+" "+theme+"'>\</div>");
|
||||
var subUl=$("<ul></ul>");
|
||||
sub.addClass('sub');
|
||||
subMenu.append(subUl);
|
||||
if(x+300>document.body.clientWidth){subMenu.addClass('left')}
|
||||
sub.append(subMenu);
|
||||
var counterForTop = -1;
|
||||
item[1].forEach(function (t) {
|
||||
if(t==='|'){
|
||||
subUl.append($('<hr/>'));
|
||||
}
|
||||
else if(typeof(t)==='string'){
|
||||
subUl.append($('<li><div class="title" title="'+ContextMenu._getMainContent(t)+'">'+t+'</div></li>'));
|
||||
counterForTop++;
|
||||
}
|
||||
else if(typeof(t)==='object'){
|
||||
var subLi=$('<li><div class="title '+(t[2]===true?'disable':'')+'" title="'+ContextMenu._getMainContent(t[0])+'">'+t[0]+'</div></li>');
|
||||
subUl.append(subLi);
|
||||
if(t[2]!==true){
|
||||
subLi.click(trigger,t[1]);
|
||||
subLi.click(function () {ContextMenu._removeContextMenu();});
|
||||
}
|
||||
counterForTop++;
|
||||
}
|
||||
});
|
||||
if(y+dom.height()>document.body.clientHeight && document.body.clientHeight>0){
|
||||
subMenu.css('top','-'+(counterForTop*30)+'px')
|
||||
}
|
||||
}
|
||||
else if(typeof(item[1])==='function' &&item[2]!==true){
|
||||
sub.click(trigger,item[1]);
|
||||
sub.click(function () {ContextMenu._removeContextMenu();});
|
||||
}
|
||||
}
|
||||
});
|
||||
//修正坐标
|
||||
if(y+dom.height()>document.body.clientHeight && document.body.clientHeight>0){y-=dom.height()}
|
||||
dom.css({
|
||||
top:y,
|
||||
left:x,
|
||||
});
|
||||
},
|
||||
_removeContextMenu:function () {
|
||||
$('.'+ContextMenu._className).remove();
|
||||
},
|
||||
};
|
||||
|
||||
$(document).click(function (e) {
|
||||
if ($(e.target).hasClass(ContextMenu._className) || $(e.target).parents('.'+ContextMenu._className).length > 0) return;
|
||||
ContextMenu._removeContextMenu();
|
||||
});
|
||||
Reference in New Issue
Block a user