- 1、需求与方案
- 1、鼠标移动悬停在单元格上,打开批注信息
- 2、当鼠标移开此批注单元格,批注信息自动消失;
- 3、批注信息需要尽量显示完整,所以要求批注单元格在浏览器上方,批注就显示在批注单元格下面,批注单元格在浏览器下方,批注信息就显示在单元格上面;
- 4、打开的批注信息必须挨着批注单元格进行打开,因为鼠标移开批注单元格,移动到批注信息上,信息窗口需要保留;
- 2、实现思路
以下步骤都是根据layer弹窗来走的
- 1、鼠标放在有批注的单元格上,触发鼠标onmouseover事件,在onmouseover事件中会做以下事情
- a. 首先关闭弹窗(layer.closeAll()?
- b. 根据弹窗的大小计算新的弹窗位置(也就是计算上边距和左边距)
- c. 打开新弹窗
- 2、鼠标离开有批注的单元格,触发鼠标mouseleave事件,在mouseleave事件中会做以下事情
- a. 首先找到弹窗的位置以及获取到弹窗大小
- b. 获取鼠标离开的位置
- c. 判断鼠标离开的位置是否在弹窗页面里面,这里分两种情况
* i. 是的情况,将弹窗页面绑定一个鼠标离开事件mouseleave,如果鼠标离开了这个弹窗页面就关闭弹窗(layer.closeAll()?
* ii. 否的情况,鼠标没有进入弹窗页面,直接关闭弹窗(layer.closeAll()?
部分代码如下:
1、首先绑定事件给需要加额外信息的单元格
var onlycol = targetTR.find("td").eq(x); // 需要加批注的单元格
onlycol.css({"background-color" : json.BACKGROUND}); // 加个背景色
$(onlycol).mouseover(onlycolOnMouseOverEvent); // 绑定鼠标移入事件触发函数onlycolOnMouseOverEvent
$(onlycol).mouseleave(onlycolOnMouseOutEvent); // 绑定鼠标移出事件触发函数onlycolOnMouseOutEvent
2、鼠标悬停事件处理
function onlycolOnMouseOverEvent(e, self) {
debugger;
if (!self)
self = getCellObject(e, self); // 获取单元格对象
if (!self)
return false;
// 用于获取单元格相对于视窗的位置集合。集合中有top, right, bottom, left, height, width等属性。
var rect = self.getBoundingClientRect();
openDialog(self, rect);
// 也可以设置延时操作,避免频繁请求打开弹窗
// self._showDialogtimeout = setTimeout(function() {
// var rect = self.getBoundingClientRect();
// openDialog(self, rect);
// }, 500);
}
3、打开弹窗页面
function openDialog(self, rect) {
layer.closeAll(); // 首先关闭所有弹窗,确保页面中只存在一个弹窗
self.lay = layer.open({
type : 2,
content : 'http://www.baidu.com', // 需要打开的地址
title : false,
area : [ '350px', '200px'],
offset : calcDialogPosition(rect, 350, 200), // 计算上边距和左边距
shade:0, // 不显示遮罩,也就是非模态窗口
btn:false, // 关闭按钮不显示
closeBtn: 0, // 右上关闭按钮不显示
anim: -1 , // 弹出动画,显示为无
success : function(layero) {
layero.css("opacity", "0.5");
}
});
}
4、计算弹窗的位置
function calcDialogPosition(rect, dialogWidth, dialogHeight) {
var body = this.document.body;
var width = body.clientWidth; // 整个窗口的宽
var height = body.clientHeight; // 整个窗口的高
var cellWidth = rect.width; // 表元的宽
var cellHeight = rect.height; // 表元的高
var cellLeft = rect.left; // 表元左边距
var cellTop = rect.top; // 表元上边距
if ((cellLeft + cellWidth + dialogWidth) < width && (cellTop + cellHeight + dialogHeight) < height) {
return [cellTop + cellHeight*2/3 + 'px', cellLeft + cellWidth*2/3 + 'px']; // 右下 有足够放弹窗的位置
} else if ((cellLeft + cellWidth*2/3 + dialogWidth) < width && (cellTop > dialogHeight)) {
return [cellTop - dialogHeight + cellHeight*1/3 + 'px', cellLeft + cellWidth*2/3 + 'px']; // 右上
} else if ((cellLeft + cellWidth*1/3) > dialogWidth && (cellTop < dialogHeight) && (cellTop + cellHeight + dialogHeight) < height){
return [cellTop + cellHeight*2/3 + 'px', cellLeft - dialogWidth + cellWidth*1/3 + 'px']; // 左下
} else if ((cellLeft + cellWidth*1/3) > dialogWidth && (cellTop > dialogHeight)) {
return [cellTop - dialogHeight + cellHeight*1/3 + 'px', cellLeft - dialogWidth + cellWidth*1/3 + 'px']; // 左上
}
}
5、 鼠标移出事件处理
function onlycolOnMouseOutEvent(e, self) {
debugger;
e = e || event || getRootWindow()["event"];
if (!self)
self = getCellObject(e, self);
if (!self)
return false;
//"#layui-layer"+layer.index 根据layer.index 找到对应显示的弹出框自定义页面
var width, height, offset, top, left;
if($("#layui-layer"+layer.index)) {
width = $("#layui-layer"+layer.index).width();
height = $("#layui-layer"+layer.index).height();
offset = $("#layui-layer"+layer.index).offset();
if(offset) {
top = offset.top;
left = offset.left;
} else {
return;
}
} else {
return;
}
//鼠标位置
var mouseX = e.pageX;
var mouseY = e.pageY;
// 判断鼠标位置是否进入了弹窗,如果是,给弹窗加一个鼠标离开事件,离开弹窗时再关闭;如果不是,关闭弹窗
if((mouseX > left && mouseX < left+width+4) && (mouseY > top && mouseY < top+height+4)){
$("#layui-layer"+layer.index).on("mouseleave",function(e){
if (self._showDialogtimeout) {
clearTimeout(self._showDialogtimeout);
}
layer.closeAll();
});
}else{
if (self._showDialogtimeout) {
clearTimeout(self._showDialogtimeout);
}
layer.closeAll();
}
}
6、比较一下mouseout事件mouseout事件
- mouseout 事件
不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。也就是说,离开绑定了mouseout事件的父标签进入子标签也会触发mouseout 事件。 - leave 事件
只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。也就是说,离开绑定了mouseleave 事件的父标签进入子标签并不会触发mouseleave 事件。