[对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: ,
offsetY: ,
textLimit: ,
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"> </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(, 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改进] 解决右键菜单栏在边缘弹出后,移出视图区域无法操作的问题的更多相关文章
- [smartMenu.js] 一个基于jquery的实用的右键拓展菜单栏插件
正在为电子书阅读器添加精准易用的标记功能,其中一个方案是扩展阅读器界面的右键菜单栏,使得用户右键点击某个词.子句.段落的时候可以进行扩展操作. 右键菜单栏有很多基于jQuery的插件,其中灵活性比较强 ...
- 解决 sublime text 3 右键菜单栏出现多余的菜单项分隔符的问题
很早之前装了一个插件 JavaScript Completions,虽然还没有用过它的高级功能,但随着 sublime text 3 逐渐成为我主要的编程工具,最近发现在右键点击文件出现的菜单栏中,菜 ...
- js去掉浏览器右键点击默认事件(+vue项目开启右键行为)
js去掉浏览器右键点击默认事件 1.阻止整个页面所有的右击事件 document.oncontextmenu = function(){ return false;} 2.特定的区域/元素 docum ...
- webdriver处理鼠标右键菜单栏
selenium中ActionChains类提供了鼠标操作的常用方法,但对于鼠标右键的菜单栏,无论是send_keys(Keys.ARROW_DOWN)还是send_keys("K" ...
- js屏蔽浏览器右键菜单,粘贴,复制,剪切,选中(转)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Jquery方法load之后导致js失效解决方法
Jquery方法load之后导致js失效解决方法 >>>>>>>>>>>>>>>>>>> ...
- 将sublimeText添加到鼠标右键菜单栏
将sublimeText添加到鼠标右键菜单栏主要是写一个注册表的文件,将这个注进去,首先你需要清楚你的sublimeText软件的安装路径,然后改一下下面这段代码就可以了 Windows Regist ...
- C# winfrom容器布局与工具栏&&右键菜单栏&&隐藏显示小图标的的简单事件
前两天的时候学习了winfrom,简单地说就是各种布局,然后给按钮,textbox等各种控件添加各种事件的操作,经过前天一晚上,昨天一天的练习操作的还算熟练,但是对构造函数传值还是不是很了解,由于各种 ...
- js进阶解决浏览器缓存不能自动更新的问题(在ajax的url上带上一个参数,可以是日期,或者是随机数)(随机数Math.random)(取得日期的毫秒数:new Date().getTime();)
js进阶解决浏览器缓存不能自动更新的问题(在ajax的url上带上一个参数,可以是日期,或者是随机数)(随机数Math.random)(取得日期的毫秒数:new Date().getTime();) ...
随机推荐
- Fastify 系列教程一(路由和日志)
介绍 Fastify是一个高度专注于以最少开销和强大的插件架构,为开发人员提供最佳体验的Web框架. 它受到了 Hapi 和 Express 的启发,是目前最快的 Node 框架之一. Fastify ...
- OOAD-设计模式(二)之GRASP模式与GOF设计模式概述
一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
- 我的第一个python web开发框架(13)——工具函数包说明(四)
string_helper.py是字符串操作包,主要对字符串进行检查.过滤和截取等处理. #!/usr/bin/evn python # coding=utf-8 import re def chec ...
- Ubuntu/deppin 系统安装Nginx
Ubuntu/deppin 系统安装Nginx 添加密钥 打开Nginx官网 ,并找到如下位置: 在桌面新建"nginx_signing.key"文件,文件内容为请点击图1中的标注 ...
- canvas绘制太阳系
原文地址:http://jeffzhong.space/2017/10/26/solar/ 学习canvas有一段时间了,顺便写个小项目练手,该项目用到的知识点包括: ES6面向对象 基本的三角函数 ...
- LeetCode 238. Product of Array Except Self (去除自己的数组之积)
Given an array of n integers where n > 1, nums, return an array output such that output[i] is equ ...
- Appium python自动化测试系列之页面滑动原理讲解(十)
10.1.1 页面滑动原理分析 在页面滑动查找章节我们就讲了滑动的知识点,只是不知道大家是否有认真练习以及去理解,如果你认真练习.理解了那么我相信这一章节的东西不用看也能够完成,下面我们还是简单分析一 ...
- swift 之 函数
swift的函数跟脚本语言有很多神似之处. 如果有一天用swift开发服务器 ,很期待哇(一切皆有可能,毕竟人家说要跑在Linux上),
- C#读写Shapefile
Shapefile文件是ArcGIS存储矢量要素的标准格式,要读写Shapefile最简单的方法当然是基于ArcObject(或者ArcEngine)开发,不过网上也有一些开源的解译Shapefile ...
- Luck and Love(二维线段树)
Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...