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

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

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

     但是作者应该是已经不再维护了,最后一个版本还是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);

    修改之后的效果:

    在右下方召唤

    在左下方召唤

    在左上方召唤

    在右上方召唤

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

  • 相关阅读:
    mysql concat
    (三)微信小程序之发送服务通知(模板消息)
    小型web服务器thttpd的学习总结(下)
    小型web服务器thttpd的学习总结(上)
    平方根倒数快速算法
    微信公众平台服务框架
    静态库动态库回顾
    RocketMQ常用命令
    rocketmq配置文件参数(broker-xx.properties)
    RocketmMQ的组成及相关概念
  • 原文地址:https://www.cnblogs.com/xiaozhaoqi/p/7978195.html
Copyright © 2011-2022 走看看