【概述】几乎每个企业都有自己的核心东西或说是框架性的东西,框架的好处是将我们经常要使用的功能,控件等包装一个个
易于使用的单元,就算是初学者也极其容易上手,减少项目的开发成本。因此框架的重要性和好处是不言而喻的。在我的这个系列
(一点一滴打造我们自己的web开发框架系列 )当中,我将自己在开发过程中用到的一些东西陆续公布出来,和大家一起交流学习。
闲话少叙,我们在开发系统的过程中经常需要给web页面设定右键菜单,在这篇文章中我实现一个客户端的右键菜单,在下一篇
中我将把它包装成一个服务器控件。言归正传吧.......
我们先来考虑下右键菜单的需求吧,首先我们需要构造函数,其次我们需要显示(show)和隐藏(hide),我们还需要添加菜单项
(add_MenuItem)和移除菜单项(remove_MenuItem),我们还需要将菜单设定到某个web页面上的dom元素(set_ContextMenu),
另外我们还需要初始化(initialize)函数来初始化一些属性和绑定一些事件,和dispose移除不再使用属性的值,最后为了让我们的菜单
能显示的漂亮一点,我们需要设定菜单项的样式(MenuItemStyle),分割栏的样式(SeparatorMenuItemStyle),及菜单容器的样式
(MenuStyle),以及鼠标滑过菜单项和滑出菜单项的样式。最后还需要每个菜单项的构造函数。
知道需求后,我们来一步步实现。
构造函数:
代码
function WebContextMenu(menuId, container, width, lineHeight) {
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;
}
接下来实现上面提到的每个方法:
代码
WebContextMenu.prototype = {
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;
}
};
再实现每个菜单项目的构造函数:
代码
function WebContextMenu.MenuItem(text, img, handler) {
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代码
代码
<div id="divSpan" style="color:Red;font-size:14px;font-weight:bold;height:123px;300px;background-color:#789ccd"></div>
js代码:
代码
var WebContextMenu1 = new WebContextMenu("WebContextMenu1","divSpan");
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方法,不贴代码了。
如果你是想在页面初始化就绑定一个右键菜单(当然你也可以在某个控件的客户端事件中绑定右键菜单,随便你了)
代码
$(document).ready(function() {WebContextMenu1.set_ContextMenu('divSpan');});
这样一个简单的右键菜单就成了,截个图大家看看。当然你可以根据你实际项目的需要添加更多的方法,和修改样式。欢迎批评指正!在下一篇中我将其包装成服务器控件,可以通过服务器端来添加菜单,或者直接从工具栏拖到页面上方便使用。
图一:右键单击
图二:选择添加右键菜单,处理相应事件