索引
ht.widget.ContextMenu
可以使任意HTML
元素响应右键菜单,支持任意层次子菜单,图片ICON
,Check
多选,Radio
单选,禁用菜单项以及自定义菜单样式,
在正式使用API
之前,您的页面里应该引入相关的js
文件:
<script src="ht.js"></script> <!--先引入ht.js-->
<script src="key.js"></script> <!--快捷键常量,可以按需引入-->
<script src="ht-contextmenu.js"></script>
ContextMenu
提供的API
如下:
setItems(json)
设置菜单项,参数为JSON
对象addTo(dom)
参数为HTML
元素,使其支持右键菜单dispose()
销毁此右键菜单show(x, y)
显示菜单,x
,y
为菜单显示页面在中的坐标hide()
隐藏菜单enableGlobalKey()
启用全局快捷键,一旦启用此选项,菜单不再使用时需要显式调用dispose()
销毁菜单disableGlobalKey()
禁用全局快捷键beforeShow(event)
菜单显示之前被调用,可以重写此方法实现动态菜单功能getItemByProperty(property, value)
查找属性名为property
,值为value
的菜单项,只返回第一个查找结果,注意:如果菜单显示时修改此查找结果,则菜单界面在下次显示时更新afterShow(event)
菜单显示之后被调用afterHide()
菜单隐藏之后被调用isShowing()
检测菜单是否显示setLabelMaxWidth(width)
设置菜单中label
的最大宽度,如果label
过长会出现跑马灯效果setVisibleFunc(function(item) {return true/false})
设置可见过滤器右键菜单的内容由一个固定格式的JSON
对象描述,包括菜单项的文字,图片以及相应的动作,下面的JSON
描述了一个典型的右键菜单:
var json = [
{
label: "CheckMenuItems", //菜单文字
items: [
{
label: "Check1",
icon: iconSrc, //菜单图片ICON
type: "check" //可多选的菜单项
},
{
label: "Check2",
icon: iconSrc,
type: "check"
},
{
label: "Check3",
icon: iconSrc,
type: "check",
items: [
{
label: "AAAA"
},
{
label: "BBBB"
},
{
label: "CCCC"
},
{
label: "DDDD"
},
{
label: "EEEE"
},
//...
]
}
]
},
{
label: "RadioMenuItems",
items: [
{
label: "Radio1",
icon: iconSrc,
type: "radio", //单选菜单项
groupId: 1 //菜单项分组
},
{
label: "Radio2",
icon: iconSrc,
type: "radio",
groupId: 1
},
{
label: "Radio3",
icon: iconSrc,
type: "radio",
groupId: 1
}
]
},
"separator", //分割线
{
label: "Menu1(disabled)",
disabled: true //禁用菜单项,可以是函数,由返回值决定是否禁用
},
{
label: "Menu2",
action: function(item, event) {
alert("you clicked:" + item.label + ",this=" + this);
},
scope: "hello" //指定回调函数中的this
},
{
label: "Menu3",
icon: iconSrc,
action: function(item) {
alert(item.label);
},
items: [
{
label: "Homepage",
href: "http://www.hightopo.com", //超链到某个URL
linkTarget: "_blank", //超链目标,默认_self
key: [Key.ctrl, Key.enter], //实际响应的快捷键
suffix: "Ctrl+Enter", //在菜单上显示的提示文字
preventDefault: false //是否阻止快捷键默认的行为,默认为true
},
{
label: "submenu2",
action: function(item) {
alert(item.label);
}
}
]
}
//...
];
这个JSON
对象渲染出来的右键菜单见下例:
var contextmenu = new ht.widget.ContextMenu(json);
contextmenu.addTo(document.getElementById("div"));
如何定制更丰富的样式参考:自定义菜单样式
某些情况下需要根据点击的内容决定右键菜单内容,例如在拓扑上根据点击的Node
显示不同的右键菜单项,
我们可以在右键菜单显示出来之前做一些处理,参考下面的示例:
var json1 = [{label: "sendToTop"},{label: "sendToBottom"}],
json2 = [{label: "Copy"},{label: "Paste"}];
var graphView = new ht.graph.GraphView(),
view = graphView.getView(),
style = view.style,
dataModel = graphView.dm();
//此处省略初始化Node的代码
//此处省略设置view样式的代码
document.body.appendChild(view);
var contextmenu = new ht.widget.ContextMenu();
//重写beforeShow,动态设置菜单项
contextmenu.beforeShow = function(e) {
var data = graphView.getDataAt(e);
if (data === node1) {
this.setItems(json1);
} else if (data === node2) {
this.setItems(json2);
} else {
this.setItems(null); //参数为null不会阻止浏览器默认的右键菜单,如果要阻止,可将参数设为空数组:[]
}
};
contextmenu.addTo(view);
接下来我们用可见过滤器实现动态菜单:
var contextmenu = new ht.widget.ContextMenu(json);
contextmenu.setVisibleFunc(function(item) {
var data = graphView.sm().ld();
if (data === node1) {
if (item.fordata === 1) {
return true;
} else {
return false;
}
} else if (data === node2) {
if (item.fordata === 1) {
return false;
} else {
return true;
}
}
});
这个例子里我们把所有的菜单项全部加到右键菜单里,然后通过visibleFunc
决定菜单项是否可见
右键菜单的样式可以使用全局的htconfig
对象配置整体风格,可配置的参数如下:
Default.contextMenuLabelFont
文字字体,默认为(isTouchable ? '16' : '13') + 'px arial, sans-serif'
Default.contextMenuLabelColor
文字颜色,默认为 #000
Default.contextMenuBackground
背景颜色,默认为#fff
Default.contextMenuDisabledLabelColor
被禁用的菜单项的文字颜色,默认为#888
Default.contextMenuHoverBackground
鼠标划过的菜单项的背景颜色,默认为#648BFE
Default.contextMenuHoverLabelColor
鼠标划过的菜单项的文字颜色,默认为#fff
Default.contextMenuSeparatorWidth
分割线的宽度,默认为1
Default.contextMenuSeparatorColor
分割线的颜色,默认为#E5E5E5
Default.contextMenuScrollerColor1
滚动按钮渐变的开始颜色,默认为#FDFDFD
Default.contextMenuScrollerColor2
滚动按钮渐变的结束颜色,默认为#D3D3D3
,Default.contextMenuScrollerBorderColor
滚动按钮的边框颜色,默认为#C3C3C3
Default.contextMenuBorderColor
菜单的边框颜色,默认为#C3C3C3
Default.contextMenuShadowColor
菜单阴影的颜色,默认为rgba(128, 128, 128, 0.5)
Default.contextMenuCheckIcon
多选按钮的图片,可以是图片url
、base64
字符串或是通过ht.Default.setImage
注册是图片名Default.contextMenuRadioIcon
单选按钮的图片,可以是图片url
、base64
字符串或是通过ht.Default.setImage
注册是图片名如下面的例子:
<script type="text/javascript">
htconfig = {
Default: {
contextMenuBackground: 'rgb(240,240,240)',
contextMenuLabelColor: 'black',
contextMenuHoverBackground: 'rgb(28,161,251)',
contextMenuHoverLabelColor: 'black',
contextMenuCheckIcon: 'checkIcon',
contextMenuRadioIcon: 'radioIcon',
contextMenuSeparatorColor: 'rgb(145,165,200)',
contextMenuScrollerBorderColor: 'rgb(145,165,200)',
contextMenuBorderColor: 'rgb(145,165,200)'
}
}
</script>
经过渲染,菜单显示如下例所示:
右键菜单样式也可以通过css
控制,由于右键菜单的内部采用行内样式,用户自定义样式需要!important
关键字才能将其覆盖,看下面的例子:
.ht-widget-contextmenu ul { /*ul是.menu-item的父节点*/
background: url("data:image/png;...") repeat-y rgb(240, 240, 240) !important; /*背景色及竖分割线画到ul上*/
background-position: -webkit-calc(1.4em + 4px) 0px !important; /*竖分割线的位置(safari6.x)*/
background-position: calc(1.4em + 4px) 0px !important; /*竖分割线的位置*/
border-radius: 0 !important;/*去掉圆角*/
}
.ht-widget-contextmenu .menu-item { /*菜单项相关样式*/
background: rgba(0,0,0,0) !important; /*背景色改为透明,显示ul的背景*/
color: black !important; /*文字颜色*/
border: 1px solid rgba(0,0,0,0) !important; /*透明边框*/
border-radius: 2px !important; /*圆角*/
margin: 3px 2px !important; /*设置margin*/
}
.ht-widget-contextmenu .menu-item.menu-item-hover {
/*鼠标滑过菜单项时,设置半透明的渐变背景色*/
background: -webkit-linear-gradient(top, rgba(193,222,255,0.2),rgba(193,222,255,0.4)) !important;
background: linear-gradient(to bottom, rgba(193,222,255,0.2),rgba(193,222,255,0.4)) !important;
color: black !important;
border: 1px solid rgb(183,212,246) !important;
}
.ht-widget-contextmenu .menu-item.disabled { /*自定义已禁用菜单项的背景色和文字颜色*/
color: #888 !important;
background: rgba(0,0,0,0) !important;
}
.ht-widget-contextmenu .menu-item.disabled.menu-item-hover { /*自定义鼠标滑过已禁用菜单项时,菜单项的背景色,文字颜色及边框*/
color: #888 !important;
background: rgba(0,0,0,0) !important;
border: 1px solid rgba(0,0,0,0) !important;
}
.ht-widget-contextmenu .prefix {
margin-right: 0.8em !important; /*设置菜单项前缀和内容之间的距离*/
}
.ht-widget-contextmenu .suffix {
margin-left: 3em !important; /*设置菜单项后缀和内容之间的距离*/
margin-right: 1em !important; /*设置菜单项后缀和边缘之间的距离*/
}
.ht-widget-contextmenu .separator { /*分割条样式*/
margin-left: -webkit-calc(1.4em + 5px) !important;
margin-left: calc(1.4em + 5px) !important;
height: 2px !important;
background-image: -webkit-linear-gradient(top, rgb(226,226,226), rgb(226,226,226) 50%,rgb(252,252,252) 50%,rgb(252,252,252)) !important;
background-image: linear-gradient(to bottom, rgb(226,226,226), rgb(226,226,226) 50%,rgb(252,252,252) 50%,rgb(252,252,252)) !important;
}
注意菜单项(.menu-item
)的结构:
其中prefix
和suffix
有对应的样式类名,我们可以通过修改它们设置菜单项内部元素之间的间距。
效果如下:
通常菜单通过右键触发显示即可,除此之外,ContextMenu
也支持通过API
控制显示和隐藏:
//显示菜单
function show() {
var x = parseInt(document.getElementById("menux").value),
y = parseInt(document.getElementById("menuy").value);
if (!isNaN(x) && !isNaN(y)) {
contextmenu.show(x,y);
}
}
//隐藏菜单
function hide() {
contextmenu.hide();
}