javascript - 使用 css 在单击更多按钮时带来上下文菜单
问题描述
我的要求是在单击树节点上的更多按钮时显示一个菜单。它应该靠近单击的节点。您可以看到更多选项图标仅悬停在树节点上。以下是我现在使用的 HTML 和 CSS 代码。
.tree ul {
margin-left: 20px;
}
.tree li {
list-style-type: none;
margin:15px;
position: relative;
cursor: pointer;
}
.tree li .submenuBtn{
margin-left:8px;
display: none;
font-weight:bolder;
}
.tree li a:hover .submenuBtn{
display: inline-block;
}
.tree li img::clicked + #contextMenu{
display: inline-block;
}
.tree li::before {
content: "";
position: absolute;
top:-7px;
left:-20px;
border-left: 1px solid #ccc;
border-bottom:1px solid #ccc;
border-radius:0 0 0 0px;
width:20px;
height:15px;
}
.tree li::after {
position:absolute;
content:"";
top:8px;
left:-20px;
border-left: 1px solid #ccc;
border-top:1px solid #ccc;
border-radius:0px 0 0 0;
width:20px;
height:100%;
}
.tree li:last-child::after {
display:none;
}
.tree li:last-child:before{
border-radius: 0 0 0 5px;
}
ul.tree>li:first-child::before {
display:none;
}
ul.tree>li:first-child::after {
border-radius:5px 0 0 0;
}
.tree li a {
border: 1px #ccc solid;
border-radius: 5px;
padding:5px 10px;
}
.tree li a:hover, .tree li a:hover+ul li a,
.tree li a:focus, .tree li a:focus+ul li a {
background: #ccc; color: #000;
/*border: 1px solid #000;*/
text-decoration: none;
}
.tree li a:hover+ul li::after, .tree li a:focus+ul li::after,
.tree li a:hover+ul li::before, .tree li a:focus+ul li::before
.tree li a:hover+ul::before, .tree li a:focus+ul::before
.tree li a:hover+ul ul::before, .tree li a:focus+ul ul::before{
/*border-color: #000; */
/*connector color on hover*/
}
<ul class="tree">
<li><a>Parent 1 <div class="submenuBtn">:</div></a></li>
<li><a>Parent 2<div class="submenuBtn">:</div></a></li>
<li>
<a>Parent 3<div class="submenuBtn">:</div></a>
<ul>
<li>
<a>1st Child of 3<div class="submenuBtn">:</div></a>
<ul>
<li><a>1st grandchild<div class="submenuBtn">:</div></a></li>
<li><a>2nd grandchild<div class="submenuBtn">:</div></a></li>
</ul>
</li>
<li><a>2nd Child of 3<div class="submenuBtn">:</div></a></li>
<li><a>3rd Child of 3<div class="submenuBtn">:</div></a></li>
</ul>
</li>
<li>
<a>Parent 4<div class="submenuBtn">:</div></a>
<ul><li><a>Parent 4's only child<div class="submenuBtn">:</div></a></li></ul>
</li>
</ul>
是否可以为此目的重用单个上下文菜单,或者我需要将菜单与每个节点一起添加。
解决方案
通过模板重用上下文菜单当然更有效,而不是重复菜单作为每个节点的子元素。
Javascript是要走的路。
有很多方法可以在 JS 中进行模板化。您可以查看诸如Mustache、Handlebars或Underscore之类的模板系统,尤其是当您需要在所有地方进行模板时,例如在单页应用程序中。
如果你的模板需求是一次性的,那么你可以做一个简单的 Javascript 解决方案,如下所示:
1.定义模板
选项 1 - 将模板完全存储在 JS 中:
var myTemplate = '<h1>MENU</h1><div class="menu_links"><a href="link1.html" class="menu_link">Link 1</a><a href="link2.html" class="menu_link">Link 2</a></div>';
选项 2 - 将模板存储在页面中:
作为一个 HTML 元素,用 CSS 从视图中隐藏,但仍然在页面 DOM 中......
<div id="template_menu" style="visibility: hidden;"><h1>MENU</h1><div class="menu_links"><a href="link1.html" class="menu_link">Link 1</a><a href="link2.html" class="menu_link">Link 2</a></div></div>
...或者在一个脚本标签中,它完全将它从页面 DOM 中隐藏起来,不需要 CSS,但仍然可以被 JS 访问:
<script id="template_menu" type="x-template">
<h1>MENU</h1><div class="menu_links"><a href="link1.html" class="menu_link">Link 1</a><a href="link2.html" class="menu_link">Link 2</a></div>
</script>
选项 2 续:在任何一种情况下,如果模板存储在页面中,则需要在 JS 中声明元素:
var myTemplate = document.getElementById("template_menu");
2.在JS中使用菜单模板
最终,除了一堆其他 JS 函数和侦听器之外,您将如何使用模板来获得完整的体验:
function openSubMenu(e) {
// First, make a new element
var newElement = document.createElement("div");
// Apply the contents of the template to your new element
newElement.innerHTML = myTemplate.innerHTML;
// Append the new element into the DOM. Here I'm adding it to the parent of the clicked element, but it's up to you how you want to structure things.
e.parentElement.appendChild(newElement);
}
最终可能会有一个聪明、笨拙的纯 CSS 解决方案,可能使用 HTML5 数据属性和隐藏的复选框,但会牺牲一些花里胡哨的东西。在模板和弹出窗口方面,相比之下,Javascript 具有相对无限的潜力。
附带说明一下,我会避免任何“悬停”功能,因为任何触摸屏用户都会对此有疑问,并且您将在 JS 中管理更多状态。如果您确实实现了悬停功能,您可能会发现最好在 JS 中与其他侦听器一起管理它,而不是在 CSS :hover 和 JS 之间折腾。
推荐阅读
- javascript - 如何将回调位置捕获到变量中?
- php - 在laravel中从字符串输入日期到mysql数据库
- python - 为什么python3不能执行一些linux命令?
- swift - 错误没有这样的模块'GoogleSignIn'Xcode 10.2
- jboss - 在 WildFly 的 keycloak 子系统中参数化安全部署名称
- javascript - 为什么使用“else if”语句会出现 NaN 错误?
- angular - 为什么选项要求花费很长时间来响应asp.net web api
- macos - Carbon API 的 64 位迁移
- java - Spring Boot - Thymeleaf 和 Json 模板
- sybase - 在sybase中触发插入另一个数据库