Jquery 类似新浪微博,鼠标移到头像,用浮动窗口显示用户信息,已做成一个jquery插件

 

   请注意!!!!! 该插件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
                                    + '"></div>';
                            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 : popover,//浮动框的DIVID,目的是可防止ID冲突
    Øpopover_wrap_id : popover_wrap,//包括浮动框和头像的外层DIVID目的是防止ID冲突,可以自行更改
    Øurl : /user/user_info_card?id=,//接收外面自定义的url
    Øuser_url : /user/user_info_card?id=,// type=prod时,使用该URL
    Øprod_url : '/user/user_info_card?id=', //type=prod时,使用该URL
    ØneedParam : true,//是否有参数,默认为true
    ØonSuccess : null, //方便以后扩展
    ØonError : null //方便以后扩展
 
 举例一:常规,使用内部定死的URL
    
       <script type=‘text/javascript’ src=‘/js/jquery.js’></script>
    <script type=‘text/javascript’ src=‘js/jquery.popovercard.js’></script>
    <a  data-obj_id=‘21‘  data-obj_type ='user' id=‘test_header’></a>  // data-popover_id=‘21’其中21是主键的值
    <script type=‘text/javascript’>
    $(function(){
    $("# test_header ").popovercard();
    });
    </script>

 

 
 
    //其中, needParam 默认也是true.如果以后想用到prod的url,改变data-obj_type=prod就可以了

举例二:使用外部自定义URL  

  
       <script type=‘text/javascript’ src=‘/js/jquery.js’></script>
    <script type=‘text/javascript’ src=‘js/jquery.popovercard.js’></script>
    <a  data-obj_id=‘21‘  data-url='/getsm/sm?id=' id=‘test_header’></a>  // data-popover_id=‘21’其中21是主键的值
    <script type=‘text/javascript’>
    $(function(){
    $("# test_header ").popovercard();
    });
    </script>

 

   //其实就是给一个data-url即可。如果不需要参数,再加data-needParam='false',删掉data-obj-id即可。

最后补充说明:

参数的设置,也可以再popovercard实例化的时候设置,效果一样
例如:
 <a  id=‘test_header’ data-obj_id=‘12’ data-obj_type=‘prod’ ></a>
<script type=‘text/javascript’>
$(function(){
$("# test_header ").popovercard();
});
</script>
等同于:
<a  id=‘test_header’></a>
<script type=‘text/javascript’>
$(function(){
$("# test_header ").popovercard({
    obj_type:‘prod’, obj_id=‘12’
});
});
</script>

  2013-06-27,对插件进行了改进,增加了自动左浮动和右浮动,并且锁定元素不再依靠id,使用class锁定元素,浮动效果如下 :

 

代码如下:

(function($) {
    var popover_card_count = 0;
    $.fn.popovercard = function(op) {
        var nowObj = $(this);
        var space = 20;// 浮动框左边空隙
        var float_width = 324;// 浮动框宽度
        var defaults = {
            obj_type : 'user',
            obj_id : '21',
            url : 'get_user_card.php?id',
            popover_class : 'popover_class',
            popover_wrap_class : 'popover_wrap_class'
        };
        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('popover_class')) != "undefined") {
            defaults.popover_class = $(this).data('popover_class');
        }
        if (typeof ($(this).data('popover_wrap_class')) != "undefined") {
            defaults.popover_wrap_class = $(this).data('popover_wrap_class');
        }
        return this.each(function(key,value) {
            var opts = $.extend(defaults, op);
            nowObj.mouseover(function() {load_user_info(opts);});
        });
        function load_user_info(opts) {
            var data_url;// 获取数据的URL
            var my_timeout;// 隐藏浮动DIV的定时器
            var popover_wrap_div;// 最外层包裹的DIV
            // 浮动框的ID
            var popover_class = opts.popover_class + '_' + popover_card_count;
            // 浮动框和IMG外面包裹的DIV的ID
            var popover_wrap_class = opts.popover_wrap_class + '_' + popover_card_count;
            if (nowObj.next("div[class*='" + opts.popover_class + "']").size() <= 0) {
                popover_card_count = popover_card_count + 1;
                data_url = opts.url + opts.obj_id;
                $.get(data_url, function(data) {
                    if (data == 'error') {
                        alert('加载失败,请联系管理员!');
                    } else {
                        if (nowObj.parent("div[class*='"+ opts.popover_wrap_class + "']").size() <= 0) {
                            // 在最外面包裹一层DIV
                            popover_wrap_div = '<div class ="' + popover_wrap_class + '"></div>';
                            nowObj.wrap(popover_wrap_div);
                        }
                        $("." + popover_wrap_class).append(data).css('float','left');
                        popover_class = $("." + popover_wrap_class + ">div:last").addClass(popover_class).attr('class');
                        resetPosition(popover_wrap_class,popover_class);
                        $("." + popover_class).show().css('float', 'right');
                        //bindEvent(popover_wrap_class, popover_class);
                    }
                });
            } else {
                popover_class = nowObj.next("div").attr('class');
                popover_wrap_class = nowObj.parent("div[class*='" + opts.popover_wrap_class + "']").attr('class');
                resetPosition(popover_wrap_class,popover_class);
            }

            // 重新定位,防止浮动框部分未显示
            function resetPosition(wrap_div_class,div_class) {
                var body_width = $("body").width();
                var body_height = $("body").height();
                var div_pop_over = $("div[class='"+div_class+"']");
                var offset = nowObj.offset();
                var left = offset.left - (space + $(div_pop_over).width());
                var right = (body_width - offset.left) - (space + $(div_pop_over).width());
                var top = offset.top - space - $(div_pop_over).height()+120-30;
                var bottom = (body_height - offset.top ) - (space + $(div_pop_over).height());
                console.log('left'+left+'right'+right+'top'+top+'bottom'+bottom);
                //头像太左边
                if(left<0){
                    $(div_pop_over).removeClass("left").addClass('right');
                }
                //头像太靠右
                if(right<0){
                    $(div_pop_over).removeClass("right").addClass('left').css('margin-left', 0-($(div_pop_over).width()+70+space));
                }
                //头像太靠上,原本需要30px,这里的数据你可以根据自己需要随意调试
                if(top<0){
                    $(div_pop_over).css('top',-30-top);
                    $(div_pop_over).find("div[class='arrow arrow-t']").css('top',60+top);
                }
                //头像太靠下
                if(bottom<0){
                    //如果使用我的页面css,不可能出现这种情况 - -,忽略不计,如果需要,按照上面的,差不多改下
                    //也挺简单的
                }
                div_class  = $(div_pop_over).attr('class');
                bindEvent(wrap_div_class, div_class);
            }
            function bindEvent(popover_wrap_class, popover_class) {
                $("div[class='"+popover_wrap_class+"']").mouseout(function() {
                    my_timeout = setTimeout(function() {
                        $("div[class='"+popover_class+"']").hide();
                    }, 100);
                    $("div[class='"+popover_wrap_class+"']").unbind('mouseout');
                }).mouseover(function() {
                    clearTimeout(my_timeout);
                });
                $("div[class='"+popover_class+"']").show().mouseover(function() {
                    clearTimeout(my_timeout);
                }).mouseout(function() {
                    my_timeout = setTimeout(function() {
                        $("div[class='"+popover_class+"']").hide();
                    }, 200);
                });
                $("div[class='"+popover_class+"']").show();return;
            }
        }
    };
})(jQuery);

 请注意!!!!! 该插件demo PHP 的 demo下载   C#.NET的demo下载

 

欢迎转载,原文地址:http://www.cnblogs.com/wangmy/p/3144723.html ,转载请注明地址,谢谢!

 

posted on 2013-06-19 18:58  稀饭里的米  阅读(4959)  评论(28编辑  收藏  举报