请注意!!!!! 该插件demo PHP 的 demo下载 C#.NET的demo下载
需要如下图,
1、鼠标移动到头像DIV时,Ajax获取数据,并让浮动DIV显示出来。
2、鼠标可以移动到上面浮动的DIV。
3、鼠标移出浮动DIV且移出头像DIV时,浮动DIV消失,
第一步,给DIV添加mouseon事件,触发获取数据:这个比较简单,我使用的是通过ajax get:$.get(url, function(data) {。。。。。}
第二步,显示DIV,
if(data=='error'){ alert('用户名片加载失败,请联系管理员!'); }else{ $(wrap_uid).append(data);//外面一层DIV,data本身就是HTML代码,当然也可以再这边先组织出data来 $(uid).show();//浮动窗口的DIV,show函数必须,不然这个新加的DIV是不会自个儿主动出来的! }
第三步,这是比较头疼的一步了,最开始,是这样的思路,给头像DIV和浮动DIV的外面那层DIV添加一个事件,mouseout事件,在事件中将浮动DIV删除
,问题来了,很多时候,用户移动到头像DIV,然后浮动DIV显示出来了,用户就想去操作浮动DIV了,但是中间是分开的!只有一个箭头是和头像DIV在一起的,也就是说,鼠标从头像DIV移动到浮动DIV时,会有很大概率跑出大的DIV,一旦鼠标进入两个DIV中间的缝隙,mouseout事件就触发了,浮动DIV就木有了,很蛋疼。
最后想了个办法,让移除浮动DIV放到一个setTimeout中,在一定的时间内(0.2s或者0.1s),若用户鼠标移动到浮动的DIV上时,触发一个clearTimeout事件,把移除浮动DIV定时器给删了!想法挺好,看着也挺简单,但是中间还是有各种BUG,各种失败,最重要的一点就是,最外面的DIV的mouseout事件需要移除绑定,自己做过实验就会知道为什么了,下面直接贴代码
function load_user_info(uid, login_id) {
var my_timeout;
var url = 'xxxxxx';
console.log(url);
$.get(url, function(data) {
console.log(data);
if(data=='error'){
alert('用户名片加载失败,请联系管理员!');
}else{
$(wrap_id).append(data).mouseout(function() {
my_timeout = setTimeout(function() {
$(float_id).remove();
}, 200);
$(wrap_id).unbind('mouseout');
}).mouseover(function() {
clearTimeout(my_timeout);
});
$(float_id).show().mouseover(function() {
clearTimeout(my_timeout);
}).mouseout(function() {
my_timeout = setTimeout(function() {
$(float_id.remove();
}, 200);
});
}
});
}
还是写点清楚吧,也算锻炼下自己的表达能力!首先,鼠标移出外层DIV时,有两种情况,一种是鼠标它真的走了,还有一种是它其实是去浮动DIV了,所以,给他200毫秒时间,时间一到,如果它没到浮动DIV,就认为它真的走了,就删掉浮动DIV,如果到了浮动DIV,就把定时器给删了!浮动DIV依旧显示,然后,从浮动DIV出来,也有两种情况,一种是去头像DIV,一种是鼠标他真的走了,老样子。至于为什么要外层的DIV解除mouseout绑定,是因为当鼠标在浮动DIV移动的时候,实际上鼠标已经移出了外层DIV的范围,当鼠标在浮动DIV上不停滑动时,mouseout事件不断触发,会造成BUG,第一次完全OK,在浮动DIV移动时,不停clearTimeout 后面timeout越来越多,第二次开始timeout就乱了,无法正确删除clearTimeout事件.....还是有点说不清,囧....
感谢@tanshaohua的指点,指出了这段代码的改进之处,就是在用户鼠标移动到头像,显示出浮动框后,鼠标再次移动到头像时,不应该再去获取数据,增加了服务器的压力。最后贴一下改进后的代码,其实就是判断下float_id的DIV是否已经存在,存在了就不进行加载。代码还比较臃肿,先把手头上其他事解决了,再来处理这个问题
var my_timeout;
if($(float_id).size()>0){
$(wrap_id).mouseout(function() {
my_timeout = setTimeout(function() {
$("float_id).remove();
}, 200);
$(wrap_id).unbind('mouseout');
}).mouseover(function() {
clearTimeout(my_timeout);
$(float_id).show().mouseover(function() {
clearTimeout(my_timeout);
}).mouseout(function() {
my_timeout = setTimeout(function() {
$(float_id).remove();
}, 200);
});
}else{
var url = 'XXXXXXX';
// console.log(url);
$.get(url, function(data) {
// console.log(data);
if(data=='error'){
alert('用户名片加载失败,请联系管理员!');
}else{
$(wrap_id).append(data).mouseout(function() {
my_timeout = setTimeout(function() {
$(float_id).remove();
}, 200);
$(wrap_id).unbind('mouseout');
}).mouseover(function() {
clearTimeout(my_timeout);
$(float_id).show().mouseover(function() {
clearTimeout(my_timeout);
}).mouseout(function() {
my_timeout = setTimeout(function() {
$(float_id).remove();
}, 200);
});
}
});
}
今天把这个功能做成了一个jquery插件:,下面是插件的代码:
(function($) {
$.fn.popovercard = function(op) {
var nowObj = $(this);
var defaults = {
obj_type : 'user',
obj_id : '21',
url : '',
user_url : '/user/user_info_card?id=',
prod_url : '/prod/prod_info_card?id',
needParam : 'true',
popover_id : 'popover',
popover_wrap_id : 'popover_wrap',
onSuccess : null,
onError : null
};
if (typeof ($(this).data('obj_id')) != "undefined") {
defaults.obj_id = $(this).data('obj_id');
}
if (typeof ($(this).data('url')) != "undefined") {
defaults.url = $(this).data('url');
}
if (typeof ($(this).data('obj_type')) != "undefined") {
defaults.obj_type = $(this).data('obj_type');
}
if (typeof ($(this).data('needParam')) != "undefined") {
defaults.needParam = $(this).data('needParam');
}
if (typeof ($(this).data('popover_id')) != "undefined") {
defaults.popover_id = $(this).data('popover_id');
}
if (typeof ($(this).data('popover_wrap_id')) != "undefined") {
defaults.popover_wrap_id = $(this).data('popover_wrap_id');
}
return this.each(function() {
var opts = $.extend(defaults, op);
nowObj.mouseover(function() {
load_user_info(opts.obj_id, opts.obj_type,opts.needParam,opts.url);
});
});
function load_user_info(uid, type,needParam,url) {
var data_url;// 获取数据的URL
var my_timeout;// 隐藏浮动DIV的定时器
var popover_wrap_div;// 最外层包裹的DIV
// 浮动框的ID
var popover_id = defaults.popover_id + '_' + type + '_' + uid;
// 浮动框和IMG外面包裹的DIV的ID
var popover_wrap_id = defaults.popover_wrap_id + '_' + type + '_'
+ uid;
if ($("#" + popover_id).size() <= 0) {
if(url==''){
if (type == 'user') {
if (needParam == 'true') {
data_url = defaults.user_url + uid;
} else {
data_url = defaults.user_url;
}
} else if (type = 'prod') {
// 扩展其他url
data_url = defaults.prod_url;
} else {
if (needParam == 'true') {
data_url = defaults.url + uid;
} else {
data_url = defaults.url;
}
}
}else{
data_url = url;
}
console.log(data_url);
$.get(data_url, function(data) {
if (data == 'error') {
alert('加载失败,请联系管理员!');
} else {
if ($("#" + popover_wrap_id).size() <= 0) {
// 在最外面包裹一层DIV
popover_wrap_div = '
<div id=""'" +="" popover_wrap_id<="" p="" style="box-sizing: border-box; color: rgb(67, 67, 67); font-family: Verdana, sans-serif, 宋体; font-size: 14px; line-height: 30px; white-space: normal; background-color: rgb(255, 255, 255);">
+ '">
';
nowObj.wrap(popover_wrap_div);
}
$("#" + popover_wrap_id).append(data);
od = $("#" + popover_wrap_id + ">div:last").attr('id',
popover_id);
$("#" + popover_id).show();
bindEvent(popover_wrap_id, popover_id);
}
});
}
bindEvent(popover_wrap_id, popover_id);
function bindEvent(popover_wrap_id, popover_id) {
$("#" + popover_wrap_id).mouseout(function() {
my_timeout = setTimeout(function() {
$("#" + popover_id).hide();
}, 200);
$("#" + popover_wrap_id).unbind('mouseout');
}).mouseover(function() {
clearTimeout(my_timeout);
});
$("#" + popover_id).show().mouseover(function() {
clearTimeout(my_timeout);
}).mouseout(function() {
my_timeout = setTimeout(function() {
$("#" + popover_id).hide();
}, 200);
});
}
}
};
})(jQuery);
接下来是使用说明:
参数说明:
Øobj_type : 'user', //类型,方便以后扩展
Øobj_id : '21’; //通过data-popover_id获取
Øpopover_id : ‘p