欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

每天学一个jquery插件-做右键菜单2

程序员文章站 2022-03-02 23:39:20
每天学一个jquery插件-做右键菜单2...

每天一个jquery插件-做右键菜单2

做右键菜单2

功能已经实现,直接对着代码讲思路了,功能可能有很多不完善的地方,但是绝对不水~

先看看示意图
每天学一个jquery插件-做右键菜单2

html部分

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>右键菜单封装</title>
		<script src="js/jquery-3.4.1.min.js"></script>
		<script src="js/yjcd.js"></script>
		<link href="css/font-awesome.min.css" rel="stylesheet" type="text/css" />
		<link href="css/yjcd.css" rel="stylesheet" type="text/css" />
		<style>
			#div1,#div2,#div3,#div4,#div5{
				border: 1px solid lightgray;
				width:200px;
				height: 200px;
				position:absolute;
				display: flex;
				justify-content: center;
				align-items: center;
			}
			#div1{
				left: 0;
				top: 0;
			}
			#div2{
				left: 200px;
				top: 200px;
			}
			#div3{
				left: 400px;
				top: 400px;
			}
			#div4{
				left: 600px;
				top: 600px;
			}
			#div5{
				left: 800px;
				top: 800px;
			}
		</style>
	</head>
	<body>
		<div id="div1">触发区域div1</div>
		<div id="div2">触发区域div2</div>
		<div id="div3">触发区域div3</div>
		<div id="div4">触发区域div4</div>
		<div id="div5">触发区域div5</div>
	</body>
</html>
<script>
	$(function(){
		var temp = yjcd({
			dom:["#div1","#div2","#div3","#div4"],
			caidan:[
				{nm:"功能1",icon:"fa-refresh",pnm:"",func:function(){console.log("功能1")}},
				{nm:"功能2",icon:"fa-paper-plane",pnm:"",func:function(){console.log("功能2")}},
				{nm:"功能3",icon:"fa-photo",pnm:"",func:function(){console.log("功能3")}},
				{nm:"功能4",icon:"fa-mail-forward",pnm:"",func:function(){console.log("功能4")}},
				{nm:"功能5",icon:"fa-hourglass-1",pnm:"",func:function(){console.log("功能5")}},
				{nm:"功能6",icon:"fa-history",pnm:"功能2",func:function(){console.log("功能6")}},
				{nm:"功能7",icon:"fa-globe",pnm:"功能3",func:function(){console.log("功能7")}},
				{nm:"功能8",icon:"fa-headphones",pnm:"功能7",func:function(){console.log("功能8")}},
				{nm:"功能9",icon:"fa-minus-square",pnm:"功能5",func:function(){console.log("功能9")}},
				{nm:"功能10",icon:"fa-plug",pnm:"功能5",func:function(){console.log("功能10")}},
				{nm:"功能11",icon:"fa-life-ring",pnm:"功能9",func:function(){console.log("功能11")}},
				{nm:"功能12",icon:"fa-envelope-open",pnm:"功能9",func:function(){console.log("功能12")}},
				{nm:"功能13",icon:"fa-fire",pnm:"功能9",func:function(){console.log("功能13")}},
				{nm:"功能14",icon:"fa-folder",pnm:"功能13",func:function(){console.log("功能14")}},
				{nm:"功能15",icon:"fa-handshake-o",pnm:"功能13",func:function(){console.log("功能15")}}
			]
		});
		var temp2 = yjcd({
			dom:["#div5"],
			caidan:[
				{nm:"功能1",icon:"fa-refresh",pnm:"",func:function(){console.log("功能1")}},
			]
		});
		temp.load();
		temp.recall('功能15',function(){
			console.log("重写15")
		})
		temp2.load();
		temp2.recall('功能1',function(){
			alert("!")
		})
	})
</script>

嗯,需要的参数应该也就是这么多了,首先给我这个弹窗要出现的位置的dom参数,然后给我菜单的配置项,依次为名称,图标,父级名称和点击触发的回调方法,当然也可以在创建弹窗实体之后重写方法
css部分

.yjcd{
	border: 1px solid lightgray;
	width: auto;
	position:fixed;
	display: none;
	box-shadow: 0 0 2px 1px black;
}
.yjcd .item{
	width: 150px;
	height: 30px;
	font-size: 14px;
	border: 1px solid lightgray;
	display: flex;
	justify-content: flex-start;
	align-items: center;
	position: relative;
	background-color: white;
	color: black;
}
.yjcd .item .nm{
	margin-left: 10px;
}
.yjcd .item .jt{
	position: absolute;
	right: 5px;
	display: none;
}
.yjcd .item:hover{
	cursor: pointer;
	background-color:black;
	color: white;
}
.yjcd .item .item{
	position: absolute;
	left:100%;
	display: none;
}

css这部分实在我渲染dom是用的类,就是控制一些样式实现效果而已,所以就是一些控制外观的类,比如要修改一些样式啥的直接在这里改就行了
js部分

var yjcd = function(op) {
	var $caidan = $("<div class='yjcd'></div>")
	$caidan.appendTo($("body"));
	for (var i = 0; i < op.caidan.length; i++) {
		var temp = op.caidan[i];
		$dom = $("<div class='item' data-index='" + i + "'><span class='fa nm " + temp.icon + "'>" + temp.nm +
			"</span><span class='fa fa-chevron-right jt'></span></div>")
		$dom.appendTo($caidan);
		temp.$dom = $dom;
		temp.isok = true;
	}
	var str = "";
	var count = 0;
	op.caidan.forEach(item => {
		if (item.pnm !== "") {
			var temp = op.caidan.find(n => n.nm == item.pnm);
			if (str == temp.nm) {
				count++;
			} else {
				str = temp.nm;
				count = 0;
			}
			item.$dom.css({
				"top": count * 30 - 1 + "px"
			})
			item.$dom.appendTo(temp.$dom);
			temp.$dom.children(".jt").show();
		}
	})
	$(".item").mouseenter(function() {
		$(this).children(".item").css("display", "flex");
	})
	$(".item").mouseleave(function() {
		$(this).children(".item").css("display", "none");
	})
	$(".item").contextmenu(function(e){
		e.preventDefault();
	})
	return {
		op: op,
		$caidan: $caidan,
		load: function() {
			var that = this;
			var str = op.dom.join(",");
			$(str).contextmenu(function(e){//禁用原本的右键菜单,同时移动自定义的右键菜单
				e.preventDefault();
				var x = e.clientX;
				var y = e.clientY;
				that.$caidan.show();
				that.$caidan.css({
					"left":x,
					"top":y
				});
				
			})
			$(document).click(function(){
				that.$caidan.hide();
			})
			$(".item").click(function(e){
				var temp = $(this).children(".jt").css("display");
				e.stopPropagation();
				if(temp=="none"){
					$caidan.hide();
					var index =$(this).attr("data-index");
					that.op.caidan[index].func();
				}
			})
		},
		recall:function(nm,func){
			var that  =this;
			var temp  =that.op.caidan.find(n=>n.nm==nm);
			temp.func = func;
		}
	}
}

  • 渲染部分
    按照代码上下书写的顺序我这里简要描述一下我的意图,首先是渲染所有的节点到右键菜单的父容器里面,这个时候所有的菜单都会存在,此时还没有实现分级的效果,不过所有的dom都已经渲染完成,然后再遍历数组进行第二次渲染,这个时候pnm这个参数就加入判断条件,将所有pnm有值得dom添加到对应的nm的dom里面去,同时还计算一下它是第几个进入同一个父级dom的对象,然后根据先后在把同父容器的子dom依次向下排列展开,这个时候分级就达成效果了,他的样式是有css与js加载过程中动态给的"top": count * 30 - 1 + "px"确定先后顺序的,接着再反向操作一波,给所有的菜单都给上箭头的图标同时判断它的子对象里面有没有包含更多菜单,再决定是不是要将这个箭头展示出来,最后通过类将所有子集菜单隐藏,一个菜单的渲染就完成了
  • 事件部分
    写上对应dom下右键菜单的事件,先禁用原生的事件然后show已经渲染完毕的菜单容器,并且通过判断此时鼠标的位置把菜单挪到鼠标下方,同时补全一些基本的触发事件菜单隐藏啥的,接着在触发的时候我这里面没有写完整,因为一个正常的参数是需要回调的时候能够给上触发事件的dom对象的,所以在方法中应该还要定义一个$dom专门存着最后一次右键点击的对象的dom,然后再用户触发菜单事件的时候调用时同时给穿上右键对象的dom和此时的鼠标event,虽然event随时都可以取到但是也必须给上。就此,功能就完成了
    ps1:回调部分其实就给替换对应参数里面的回调就行了,通过nm找到对应的那条菜单配置然后更改里面默认的回调就行了。
    ps2:鼠标悬浮到有子集的菜单上怎么只显示下一级的按钮,其实只要通过children找到控制就行了,children只是找到直接子集然后不会管间接的子集部分,当然要找到间接的部分就考虑find,不过这与需求不符,所以我用的是前者

完事,洗澡,碎觉~

本文地址:https://blog.csdn.net/weixin_44142582/article/details/112589871