【概述】几乎每个企业都有自己的核心东西或说是框架性的东西,框架的好处是将我们经常要使用的功能,控件等包装一个个
易于使用的单元,就算是初学者也极其容易上手,减少项目的开发成本。因此框架的重要性和好处是不言而喻的。在我的这个系列
(一点一滴打造我们自己的web开发框架系列 )当中,我将自己在开发过程中用到的一些东西陆续公布出来,和大家一起交流学习。
闲话少叙,我们在开发系统的过程中经常需要给web页面设定右键菜单,在这篇文章中我实现一个客户端的右键菜单,在下一篇
中我将把它包装成一个服务器控件。言归正传吧.......
我们先来考虑下右键菜单的需求吧,首先我们需要构造函数,其次我们需要显示(show)和隐藏(hide),我们还需要添加菜单项
(add_MenuItem)和移除菜单项(remove_MenuItem),我们还需要将菜单设定到某个web页面上的dom元素(set_ContextMenu),
另外我们还需要初始化(initialize)函数来初始化一些属性和绑定一些事件,和dispose移除不再使用属性的值,最后为了让我们的菜单
能显示的漂亮一点,我们需要设定菜单项的样式(MenuItemStyle),分割栏的样式(SeparatorMenuItemStyle),及菜单容器的样式
(MenuStyle),以及鼠标滑过菜单项和滑出菜单项的样式。最后还需要每个菜单项的构造函数。
知道需求后,我们来一步步实现。
构造函数:
this .MenuId = menuId;
this .Width = typeof (width) == ' undefined ' ? ' 180px ' : width;
this .LineHeight = typeof (lineHeight) == ' undefined ' ? ' 23px ' : lineHeight;
this .Container = container;
this .MenuItemList = [];
this .MenuElement = null ;
this .MenuItemStyle = { " list-style " : " none " , " border " : " 1px solid #efefef " , " font-size " : " 12px " , " margin-top " : " 1px " , " background-color " : " lightyellow " };
this .ActiveMenuItemStyle = { " background-color " : " #8cdfff " , " cursor " : " hand " };
this .SeparatorMenuItemStyle = { " border " : " 1px solid #ff0000 " , " height " : " 2px " , " background-color " : " #ffffff " };
this ._currentMenu = null ;
this ._oldItem = null ;
this ._normalMenuItemCount = 0 ;
this ._separatorMenuItemCount = 0 ;
}
接下来实现上面提到的每个方法:
initialize: function () {
var context = this ;
$(document).bind( " click " , function () {
if (context._currentMenu != null )
context.hide();
})
},
_createMenuContainer: function () {
var div = document.createElement( " DIV " );
div.setAttribute( " id " , this .MenuId);
div.style.width = this .Width;
div.style.backgroundColor = " #8cdfff " ;
div.style.border = " solid #5F5F5F 1px " ;
div.style.position = " absolute " ;
div.style.zIndex = " 1000 " ;
div.style.padding = " 0px 0px 0px 0px " ;
div.style.margin = " 0px 0px 0px 0px " ;
var ul = document.createElement( " UL " );
ul.style.padding = " 0px 0px 0px 0px " ;
ul.style.margin = " 0px 0px 0px 18px " ;
div.appendChild(ul);
$get( this .Container).appendChild(div);
this .MenuElement = div;
},
add_MenuItem: function (menuItem) {
this .MenuItemList.push(menuItem);
},
remove_MenuItem: function (menuItem) {
for ( var i = 0 ; i < this .MenuItemList.length; i ++ ) {
var item = this .MenuItemList[i];
if (item.Text == menuItem.Text)
Array.removeAt(i);
}
},
show: function () {
if ( this ._currentMenu != null ) this .hide();
if (window.event)
window.event.returnValue = false ;
else
event.preventDefault();
this ._createMenuContainer();
var self = $get( this .MenuId);
var ul = self.childNodes[ 0 ];
for ( var i = 0 ; i < this .MenuItemList.length; i ++ ) {
var item = this .MenuItemList[i];
var li = null ;
if (item.Text == '' ) {
li = document.createElement( " DIV " );
this ._separatorMenuItemCount ++ ;
}
else {
li = document.createElement( " LI " );
$(li).append( " <img src=' " + item.Image + " '/> <span> " + item.Text + " </span> " );
$(li).css( this .MenuItemStyle);
if ( typeof item.Handler == ' function ' )
$(li).bind( " click " , item.Handler);
else
$(li).bind( " click " , eval(item.Handler));
this ._normalMenuItemCount ++ ;
$(li).bind( ' mouseover ' , this ._mouseoverItem( this ));
$(li).bind( ' mouseout ' , this ._mouseoutItem( this ));
}
ul.appendChild(li);
}
this .MenuElement.style.left = event.clientX + document.documentElement.scrollLeft;
this .MenuElement.style.top = event.clientY + document.documentElement.scrollTop;
this .MenuElement.style.height = this ._normalMenuItemCount * 23 + this ._separatorMenuItemCount * 2 + ' px ' ;
this ._currentMenu = this ;
},
_mouseoverItem: function (instance) {
var context = instance;
return function () {
$( this ).css(context.ActiveMenuItemStyle);
}
},
_mouseoutItem: function (instance) {
var context = instance;
return function () {
$( this ).css(context.MenuItemStyle);
}
},
hide: function () {
var self = $get( this .MenuId);
if (self.parentNode != null )
self.parentNode.removeChild(self);
this .dispose();
},
set_ContextMenu: function (container) {
this .Container = container;
var context = this ;
$get( this .Container).oncontextmenu = function () { context.show(); };
},
dispose: function () {
this .MenuElement = null ;
this ._currentMenu = null ;
this ._normalMenuItemCount = 0 ;
this ._separatorMenuItemCount = 0 ;
}
};
再实现每个菜单项目的构造函数:
this .Text = text;
this .Image = img;
this .Handler = handler;
}
WebContextMenu.MenuItem.prototype = {
}
完成后,我们客户端如何来调用呢,首先我们需要在aspx页面包含ScriptManager控件和jQuery.js,如果不是aspx页面,你需要自己手动将Microsoft.Ajax.js
和jquery.js包含进去(本人的癖好喜欢用这两个js库)。包含上两个js文件后,我们添加以下代码
html代码
js代码:
WebContextMenu1.add_MenuItem( new WebContextMenu.MenuItem( " 添加 " , " images/db.ico " , " add " ));
WebContextMenu1.add_MenuItem( new WebContextMenu.MenuItem( " 编辑 " , " images/db.ico " , " edit " ));
WebContextMenu1.add_MenuItem( new WebContextMenu.MenuItem( " 删除 " , " images/db.ico " , " del " ));
WebContextMenu1.add_MenuItem( new WebContextMenu.MenuItem( " 导出Excel " , " images/db.ico " , " outputExcel " ));
WebContextMenu1.add_MenuItem( new WebContextMenu.MenuItem( " 导入Excel " , " images/db.ico " , " inputExcel " ));
WebContextMenu1.initialize();
其中add,edit,del,outputExcel,inputExel为客户端js方法,不贴代码了。
如果你是想在页面初始化就绑定一个右键菜单(当然你也可以在某个控件的客户端事件中绑定右键菜单,随便你了)
这样一个简单的右键菜单就成了,截个图大家看看。当然你可以根据你实际项目的需要添加更多的方法,和修改样式。欢迎批评指正!在下一篇中我将其包装成服务器控件,可以通过服务器端来添加菜单,或者直接从工具栏拖到页面上方便使用。
图一:右键单击
图二:选择添加右键菜单,处理相应事件