js学习笔记。
鼠标右键菜单和消息窗口是由div+css样式组成,由js控制生成。不足之处在于宽度写死,如果大家有什么好的做法或者想法,或者在网上看到的好的例子,好的想法,都可以拿出来大家讨论。内容不多为了方便阅读,我将所有的代码都放在了一个html里面,包括css样式和js脚本。
遇到的一些问题和值得讨的地方都写在注释里头,在这里就不再说了。
代码在IE8, Firefox12.0, Chrome20.0.1132.5测试通过,但是不同的浏览器显示的有些许不同。
请指教!
<html>
<head>
<title>鼠标右键菜单及淡入淡出消息窗口测试</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style stype="text/css">
body{
text-align:center; /* 此设置只在IE中起效,在chrome20.0.1132.57里不能居中,只好使用<center>标签*/
}
/*鼠标右键菜单样式,主要样式如下
菜单宽度200px,高度自适应,浮动,默认隐藏,包含菜单项;
菜单项宽度100%,高度20px,包含图标、菜单名、右侧HTML元素;
菜单项图标宽度40px,高度100%,左侧浮动;
菜单名宽度130px,高度100%,距左40px;
右侧HTML宽度30px,高度100%,右侧浮动,距左170px
*/
.menu{
background-color:#c0c0c0;
border:1px solid #888888;
border-bottom:0px;
position:absolute;
width:200px;
height:auto;
display:none;
text-align:left;
padding:0px;
}
.menuItem{
border-bottom:1px solid #888888;
width:100%;
height:20px;
padding:0px;
margin:0px;
}
.menuItemOnMouseOver{
background:green;
}
.menuItemIcon{
position:absolute;
width:40px;
height:100%;
text-align:center;
padding:0px;
margin:0px;
}
.menuItemName{
position:absolute;
width:130px;
height:100%;
margin-left:40px;
padding-left:2px;
text-align:left;
}
.menuItemRight{
position:absolute;
width:30px;
height:100%;
margin-left:170px;
padding:0px;
text-align:center;
}
/*浮动消息窗口菜单样式,主要样式如下:
窗口,宽度300px,高度自适应,浮动,,默认隐藏,包含窗口标题、消息内容;
窗口标题,宽度100%,高度20px,包含标题文本、关闭按钮;
标题文本,宽高度默认,靠左;
关闭按钮,宽度20px,高度默认,鼠标上移样式为手形;
消息内容,宽度100%,高度自适应,文本换行。
*/
.msgDialog{
position:absolute;
width:300;
heigth:auto;
background-color:#c0c0c0;
text-align:left;
dislay:none;
}
.msgDialogTitle{
width:100%;
heigth:20px;
font-weight:bold;
background-color:#0000ff;
color:#ffffff;
text-align:left;
}
.msgDialogTitleText{
padding-left:3px;
/*msgDialogTitleText和dialogTitleClose同时使用display:inline;在IE中则可以使两个div在同一行上,msgDialogTitleText的宽度用js可以改变,
但是在chrome,forefox里,可以显示在同一行上,却不能修改宽度,为兼容需要,放弃这种用法,改为dialogTitleClose浮动position:absolute;*/
/*display:inline;*/
text-align:left;
margin-left:0px;
}
.dialogTitleClose{
position:absolute;
/*display:inline;*/
text-align:center;
width:20px;
cursor:hand;
margin-left:280px;
margin-top:-19px;
}
.dialogTitleCtrlOver{
background-color:#00eeff;
}
.msgDialogIcon{
position:absolute;
width:26px;
heigth:auto;
margin-top:3px;
text-align:center;
}
.msgDialogContent{
width:100%;
height:auto;
text-align:left;
padding:3px;
word-break:break-all
}
/**测试区域样式**/
.testDiv{
border:1px solid #ff0000;
position:absolute;
width:100px;
height:100px;
}
#testArea{
width:500px;
height:300px;
border:1px solid #00ff00;
text-align:left;
}
#remark{position:absolute;}
#divOne{margin-left:50px;margin-top:50px;}
#divTow{margin-left:350px;margin-top:50px;}
</style>
<script type="text/javascript">
// 鼠标右键菜单对象
var mouseMenu;
/**创建菜单项,返回DIV对象
* @param options 菜单配置项,目前只配置
1、菜单项ID itemId,
2、菜单项图标资源路径icon,
3、菜单项显示的名称name,
4、菜单项右边的html块区域内容rightHtml,可嵌入checkbox和radio等html元素,
5、菜单项点击事件处理函数onclick,
6、菜单项鼠标经过事件处理函数onmouseover,
7、菜单项鼠标移出事件处理函数onmouseout
*/
function createMenuItem(options){
if(!options){
throw "创建菜单项createMenuItem函数参数非法,必须设置菜单项参数!";
}
var itemIcon = document.createElement("div");
itemIcon.className = "menuItemIcon";
var itemIconImg = document.createElement("img");
itemIconImg.src = options.icon;
var itemName = document.createElement("div");
itemName.className = "menuItemName";
itemName.innerHTML = options.name;// firfox不支持innerText
var itemRight = document.createElement("div");
itemRight.className = "menuItemRight";
itemRight.innerHTML = options.rightHtml;
var item = document.createElement("div");
item.id = options.itemId;
item.className = "menuItem";
itemIcon.appendChild(itemIconImg);
item.appendChild(itemIcon);
item.appendChild(itemName);
item.appendChild(itemRight);
item.onclick = options.onclick;
item.onmouseover = options.onmouseover;
item.onmouseout = options.onmouseout;
return item;
}
/**初始化鼠标右键菜单,返回DIV对象**/
function doGetMenu(){
// 如果已初始化鼠标右键菜单,则直接返回
if(mouseMenu){
return mouseMenu;
}
mouseMenu = document.createElement("div");
mouseMenu.id = "menu";
mouseMenu.className = "menu";
var onclick = function(event){
msgDialog("淡出淡入消息框", "还没有做完呢,这么着急点干嘛...", "4.gif", 3000);
stopBubble(event);
}
var onmouseover = function(event){
this.className = "menuItem menuItemOnMouseOver";
}
var onmouseout = function(event){
this.className = "menuItem";
}
mouseMenu.appendChild(createMenuItem({itemId:"newItem", icon:"4.gif", name:"新建", rightHtml:"", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
mouseMenu.appendChild(createMenuItem({itemId:"openItem", icon:"4.gif", name:"打开", rightHtml:"", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
mouseMenu.appendChild(createMenuItem({itemId:"editItem", icon:"4.gif", name:"编辑", rightHtml:"", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
mouseMenu.appendChild(createMenuItem({itemId:"encoding", icon:"4.gif", name:"编码UTF-8", rightHtml:"<input type='checkbox' />", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
mouseMenu.appendChild(createMenuItem({itemId:"IE", icon:"4.gif", name:"使用IE", rightHtml:"<input type='checkbox' />", onclick:onclick, onmouseover:onmouseover, onmouseout:onmouseout}));
document.body.appendChild(mouseMenu);
return mouseMenu;
}
function showMenu(){
doGetMenu().style.display = "block";
}
function hideMenu(){
doGetMenu().style.display = "none";
}
/**阻断事件冒泡传递
* @param evt 事件
*/
function stopBubble(evt) {
var e = evt ? evt : window.event;// 兼容IE,Firefox,Chrome
if (window.event) {
e.cancelBubble = true;
} else {
//e.preventDefault();
e.stopPropagation();
}
}
/**鼠标右键监听器
* @param evt 点击事件
*/
function onMouseupListener(evt){
var event = evt?evt:window.event; // 兼容IE,Firefox,Chrome
if (event.button != 2) {
return ;
}
// 获取鼠标离窗口右下角的X和Y轴距离(与滚动无关)
var redge=document.body.clientWidth-event.clientX;
var bedge=document.body.clientHeight-event.clientY;
var mn = doGetMenu();
// 如果当前点击点到窗口右侧的距离小于菜单宽度,则将菜单向左弹出,否则向右弹出
if (redge<mn.offsetWidth)
{
mn.style.left=document.body.scrollLeft + event.clientX-mn.offsetWidth
}
else
{
mn.style.left=document.body.scrollLeft + event.clientX
showMenu();
}
// 如果当前点击点到窗口下侧的距离小于菜单高度,则将菜单向上弹出,否则向下弹出
if (bedge<mn.offsetHeight)
{
mn.style.top=document.body.scrollTop + event.clientY - mn.offsetHeight
}
else
{
mn.style.top = document.body.scrollTop + event.clientY
showMenu();
}
// 阻断事件冒泡传递,这一步必须
stopBubble(evt);
}
// 淡出淡入速度常量
var FADE_SPEED_MOSTFAST = 10;
var FADE_SPEED_FAST = 50;
var FADE_SPEED_NORMAL = 100;
var FADE_SPEED_SLOW = 200;
var FADE_SPEED_MOSTSLOW = 500;
/**元素淡入
* @param el 必填项,淡入的元素DOM对象,该元素position样式必须是absolute
* @param maxOpacity 元素el最大不透明度值(1~100)
* @param opacity 元素el下一个的不透明度值(1~100)
* @param callback 无参数回调函数
* @param fadeSpeed 谈入速度,可使用FADE_SPEED_FAST、FADE_SPEED_NORMAL和FADE_SPEED_SLOW,也可以自定义值(非负非零整数),值越大,速度越小
*/
function fadeIn(el, maxOpacity, opacity, callback, fadeSpeed){
if(!el){
return;
}
if(!maxOpacity){
maxOpacity = 100;
}
if(!opacity){
opacity = 0;
}
if(!fadeSpeed){
fadeSpeed = FADE_SPEED_NORMAL;
}
if(el.style.display == "none"){
el.style.display = "block";
}
opacity+=10;
if(opacity > maxOpacity){
opacity = maxOpacity;
}
el.style.filter="alpha(opacity="+opacity+")";
el.style.opacity=opacity/100;
if(opacity<maxOpacity){
setTimeout(function(){fadeIn(el, maxOpacity, opacity, callback, fadeSpeed);},fadeSpeed);
}else{
clearTimeout();
if(callback){
callback();
}
}
}
/**元素淡出
* @param el 必填项,淡出的元素DOM对象,该元素position样式必须是absolute且元素可见(display不为none)
* @param minOpacity 元素el最小不透明度值(1~100)
* @param opacity 元素el下一个的不透明度值(1~100)
* @param callback 无参数回调函数
* @param fadeSpeed 谈入速度,可使用FADE_SPEED_FAST、FADE_SPEED_NORMAL和FADE_SPEED_SLOW,也可以自定义值(非负非零整数),值越大,速度越小
*/
function fadeOut(el, minOpacity, opacity, callback, fadeSpeed){
if(!el || (el.style.display == "none")){
return;
}
if(!minOpacity){
minOpacity = 0;
}
if(!opacity){
opacity = 100;
}
if(!fadeSpeed){
fadeSpeed = FADE_SPEED_NORMAL;
}
opacity-=10;
if(opacity < minOpacity){
opacity = minOpacity;
}
el.style.filter="alpha(opacity="+opacity+")";
el.style.opacity=opacity/100;
if(opacity>minOpacity){
setTimeout(function(){fadeOut(el, minOpacity, opacity, callback, fadeSpeed);},fadeSpeed);
}
else{
clearTimeout();
if(opacity == 0){
el.style.display = "none";
}
if(callback){
callback();
}
}
}
/**淡出淡入非模式消息窗口,目前消息窗口的宽度在样式中写死,未做自适应大小(根据消息内容宽度可变)
* @param title 消息窗口标题
* @param msg 消息窗口内容
* @param icon 消息窗口图片
* @param stayTime 消息窗口停留时间(ms)
*/
function msgDialog(title, msg, icon, stayTime){
if(!title){
title = "message";
}
if(!stayTime){
stayTime = 1000;
}
// 消息窗口主体
var dialog = document.createElement("div");
dialog.className = "msgDialog";
// 消息窗口标题栏文本元素
var dialogTitleText = document.createElement("div");
dialogTitleText.className = "msgDialogTitleText";
dialogTitleText.innerHTML = title;
// 消息窗口标题栏关闭元素
var dialogTitleClose = document.createElement("div");
dialogTitleClose.className = "dialogTitleClose";
dialogTitleClose.innerHTML = "X";
dialogTitleClose.onmouseover = function(event){
this.className = "dialogTitleClose dialogTitleCtrlOver";
}
dialogTitleClose.onmouseout = function(event){
this.className = "dialogTitleClose";
}
dialogTitleClose.onclick = function(event){
fadeOut(dialog, 0, dialog.style.opacity*100, function(){
dialog = null;
}, FADE_SPEED_FAST);
}
// 消息窗口标题栏
var dialogTitle = document.createElement("div");
dialogTitle.className = "msgDialogTitle";
dialogTitle.appendChild(dialogTitleText);
dialogTitle.appendChild(dialogTitleClose);
dialog.appendChild(dialogTitle);
// 消息窗口消息图标,
if(icon){
var dialogIconImg = document.createElement("img");
dialogIconImg.src = icon;
var dialogIcon = document.createElement("div");
dialogIcon.className = "msgDialogIcon";
dialogIcon.appendChild(dialogIconImg);
dialog.appendChild(dialogIcon);
}
// 消息窗口消息内容
var dialogContent = document.createElement("div");
dialogContent.className = "msgDialogContent";
dialogContent.innerHTML = (icon ? " " : "") + msg;
dialog.appendChild(dialogContent);
document.body.appendChild(dialog);
// 调整消息窗口标题中的标题元素宽度,需要添加到body之后才能获取offsetWidth。
// dialogTitleText和dialogTitleClose同时使用display:inline时,在IE中下面的句子可以修改dialogTitleClose的宽度,但是在firefox和chrome里则不行。
// 为了浏览器兼容,所以改为dialogTitleClose样式position:absolute,并在样式中写死宽度。
// ps:这样子搞,会疯掉的。
//dialogTitleClose.style.width = dialogTitle.offsetWidth - dialogTitleClose.offsetWidth;
// 调整消息窗口位置居中
dialog.style.left = (document.body.clientWidth-dialog.offsetWidth)/2;
dialog.style.top = (document.body.clientHeight-dialog.offsetHeight)/2;
// 消息窗口淡入
fadeIn(dialog, 100,0, function(){
// 消息窗口停留stayTime毫秒后淡出
setTimeout(function(){
fadeOut(dialog, 0, 100, function(){
dialog = null;
}, FADE_SPEED_FAST);
}, stayTime);
}, FADE_SPEED_NORMAL);
}
</script>
</head>
<body>
<center>
<div id="testArea">
<div id="remark">
测试区域,右击div块弹出菜单,点击菜单项弹出淡出淡入消息框。<br/>
本程序的测试浏览器环境:IE8, Firefox12.0, Chrome20.0.1132.5<br>
<a href="http://bing-zz.iteye.com/" title="今天比昨天好" style="text-decoration:none;color:#888888;width:200px;position:absolute;margin-top:240px;margin-left:280px;">http://bing-zz.iteye.com/</a>
<div>
<div id="divOne" class="testDiv">
div块一<br/>id:divOne
</div>
<div id="divTow" class="testDiv">
div块二<br/>id:divTow
</div>
</div>
</center>
</body>
</html>
<script type="text/javascript">
document.oncontextmenu = function(){return false;}; // 屏蔽窗口右键菜单
document.getElementById("divOne").onmouseup = onMouseupListener;
document.getElementById("divTow").onmouseup = onMouseupListener;
// 窗口单击隐藏鼠标右键菜单,IE可以设置到document一层,而firefox不行,似乎在firefox里不能阻止事件传递到document
document.body.onclick = function(event){hideMenu();}
</script>