码迷,mamicode.com
首页 > Web开发 > 详细

[对smartMenu.js改进] 解决右键菜单栏在边缘弹出后,移出视图区域无法操作的问题

时间:2017-12-04 19:20:34      阅读:377      评论:0      收藏:0      [点我收藏+]

标签:ref   array   oop   display   query   view   def   append   事件   

当用户在视图边缘(如右下角)右键召唤菜单栏的时候,菜单仍然从选中元素的右下角弹出,这时二级菜单栏一般都离开了视图区域,用户无法进一步操作。

这个问题挺常见的,原作者的留言板:

技术分享图片

技术分享图片

 但是作者应该是已经不再维护了,最后一个版本还是2011年10月的。

我给出的比较初步的解决方案:

因为作者没有给出鼠标事件的接口,只能在库的源码中修改坐标计算逻辑,以达到根据位置自适应弹出菜单的目的。

思路:判断右键点击位置,与窗口(我的是iframe窗口)大小作比较,取中心点分为坐标系的四个象限。

  1、在第一象限召唤菜单栏,显示在触发事件元素的左下角

  2、在第二象限召唤菜单栏,显示在触发事件元素的左上角

  3、在第三象限召唤菜单栏,显示在触发事件元素的右上角

  4、在第四象限召唤菜单栏,显示在触发事件元素的右下角

完整的代码如下:

/*
 * smartMenu.js 智能上下文菜单插件
 * http://www.zhangxinxu.com/
 *
 * Copyright 2011, zhangxinxu
 *
 * 2011-05-26 v1.0    编写
 * 2011-06-03 v1.1    修复func中this失准问题
 * 2011-10-10 v1.2  修复脚本放在<head>标签中层无法隐藏的问题
 * 2011-10-30 v1.3  修复IE6~7下二级菜单移到第二项隐藏的问题
 */
 
(function($) {
    var D = $(document).data("func", {});    
    $.smartMenu = $.noop;
    $.fn.smartMenu = function(data, options) {
        var B = $("body"), defaults = {
            name: "",
            offsetX: 2,
            offsetY: 2,
            textLimit: 6,
            beforeShow: $.noop,
            afterShow: $.noop
        };
        var params = $.extend(defaults, options || {});
        
        var htmlCreateMenu = function(datum) {
            var dataMenu = datum || data, nameMenu = datum? Math.random().toString(): params.name, htmlMenu = "", htmlCorner = "", clKey = "smart_menu_";
            if ($.isArray(dataMenu) && dataMenu.length) {
                htmlMenu = <div id="smartMenu_+ nameMenu +" class="+ clKey +box"> +
                                <div class="+ clKey +body"> +
                                    <ul class="+ clKey +ul">;
                                    
                $.each(dataMenu, function(i, arr) {
                    if (i) {
                        htmlMenu = htmlMenu + <li class="+ clKey +li_separate">&nbsp;</li>;    
                    }
                    if ($.isArray(arr)) {
                        $.each(arr, function(j, obj) {
                            var text = obj.text, htmlMenuLi = "", strTitle = "", rand = Math.random().toString().replace(".", "");
                            if (text) {
                                if (text.length > params.textLimit) {
                                    text = text.slice(0, params.textLimit)    + "";
                                    strTitle =  title="+ obj.text +";
                                }
                                if ($.isArray(obj.data) && obj.data.length) {
                                    htmlMenuLi = <li class="+ clKey +li" data-hover="true"> + htmlCreateMenu(obj.data) +
                                        <a href="javascript:" class="+ clKey +a"+ strTitle + data-key="+ rand +"><i class="+ clKey +triangle"></i>+ text +</a> + 
                                    </li>;
                                } else {
                                    htmlMenuLi = <li class="+ clKey +li"> +
                                        <a href="javascript:" class="+ clKey +a"+ strTitle + data-key="+ rand +">+ text +</a> + 
                                    </li>;
                                }
                                
                                htmlMenu += htmlMenuLi;
                                
                                var objFunc = D.data("func");
                                objFunc[rand] = obj.func;
                                D.data("func", objFunc);
                            }
                        });    
                    }
                });
                
                htmlMenu = htmlMenu + </ul> +
                                    </div> +
                                </div>;
            }
            return htmlMenu;
        }, funSmartMenu = function() {
            var idKey = "#smartMenu_", clKey = "smart_menu_", jqueryMenu = $(idKey + params.name);
            if (!jqueryMenu.size()) {
                $("body").append(htmlCreateMenu());
                
                //事件
                $(idKey + params.name +" a").bind("click", function() {
                    var key = $(this).attr("data-key"),
                        callback = D.data("func")[key];
                    if ($.isFunction(callback)) {
                        callback.call(D.data("trigger"));    
                    }
                    $.smartMenu.hide();
                    return false;
                });
                $(idKey + params.name +" li").each(function() {
                    var isHover = $(this).attr("data-hover"), clHover = clKey + "li_hover";
                    
                    $(this).hover(function() {
                        var jqueryHover = $(this).siblings("." + clHover);
                        jqueryHover.removeClass(clHover).children("."+ clKey +"box").hide();
                        jqueryHover.children("."+ clKey +"a").removeClass(clKey +"a_hover");
                        
                        if (isHover) {                    
                            $(this).addClass(clHover).children("."+ clKey +"box").show();
                            $(this).children("."+ clKey +"a").addClass(clKey +"a_hover");    
                        }
                        
                    });
                    
                });
                return $(idKey + params.name);
            } 
            return jqueryMenu;
        };
        
        $(this).each(function() {
            this.oncontextmenu = function(e) {
                //回调
                if ($.isFunction(params.beforeShow)) {
                    params.beforeShow.call(this);    
                }
                e = e || window.event;
                //阻止冒泡
                e.cancelBubble = true;
                if (e.stopPropagation) {
                    e.stopPropagation();
                }
                //隐藏当前上下文菜单,确保页面上一次只有一个上下文菜单
                $.smartMenu.hide();
                var st = D.scrollTop();
                var jqueryMenu = funSmartMenu();
                if (jqueryMenu) {
                    /*
                        2017.12.4修改:根据触发事件的位置,自适应方向弹出
                    */
                    if( e.clientX <= (e.view.innerWidth/2) && e.clientY <= (e.view.innerHeight/2))//左上
                    {
                        jqueryMenu.css({
                            display: "block",
                            left: e.clientX + params.offsetX ,
                            top: e.clientY + st + params.offsetY ,
                        });
                    }
                    if( e.clientX >= (e.view.innerWidth/2) && e.clientY <= (e.view.innerHeight/2))//右上
                    {
                        jqueryMenu.css({
                            display: "block",
                            left: e.clientX + params.offsetX -100,
                            top: e.clientY + st + params.offsetY ,
                        });
                    }
                    if( e.clientX <= (e.view.innerWidth/2) && e.clientY >= (e.view.innerHeight/2))//左下
                    {
                        jqueryMenu.css({
                            display: "block",
                            left: e.clientX + params.offsetX ,
                            top: e.clientY + st + params.offsetY -120,
                        });
                    }
                    if( e.clientX >= (e.view.innerWidth/2) && e.clientY >= (e.view.innerHeight/2))//右下
                    {
                        jqueryMenu.css({
                            display: "block",
                            left: e.clientX + params.offsetX -100,
                            top: e.clientY + st + params.offsetY -120,
                        });
                    }
                    D.data("target", jqueryMenu);
                    D.data("trigger", this);
                    //回调
                    if ($.isFunction(params.afterShow)) {
                        params.afterShow.call(this);    
                    }
                    return false;
                }
            };
        });
        if (!B.data("bind")) {
            B.bind("click", $.smartMenu.hide).data("bind", true);
        }
    };
    $.extend($.smartMenu, {
        hide: function() {
            var target = D.data("target");
            if (target && target.css("display") === "block") {
                target.hide();
            }        
        },
        removeevent: function (event) {
            var target = D.data("target");
            if (target) {
                target.remove();
                if ($.isFunction(event)) {
                    event.call(this);
                }
            }
        },
        remove: function() {
            var target = D.data("target");
            if (target) {
                target.remove();
            }
        }
    });
})(jQuery);

修改之后的效果:

在右下方召唤技术分享图片

在左下方召唤技术分享图片

在左上方召唤技术分享图片

在右上方召唤技术分享图片

大概效果就是这样了,经过测试,菜单栏不会弹到视窗外面了。

 

[对smartMenu.js改进] 解决右键菜单栏在边缘弹出后,移出视图区域无法操作的问题

标签:ref   array   oop   display   query   view   def   append   事件   

原文地址:http://www.cnblogs.com/xiaozhaoqi/p/7978195.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!