ContextMenu and Element Selection
by vikikamath
HTML
<nav class="context-menu collapse">
<ul class="flex flex-col items">
<li id="view" class="item">View Component</li>
<li id="edit" class="item">Edit Component</li>
<li id="delete" class="item">Delete Component</li>
</ul>
</nav>
<main>
<div class="flex flex-row flex-wrap">
<div id="1" class="post blue flex flex-row flex-wrap" data-attr="INVESTMENT_ACCOUNT.accountNameLabel">
<div id="1.1" class="post yellow"></div>
<div id="1.2" class="post yellow flex flex-row flex-wrap">
<div id="1.2.1" class="post green"></div>
<div id="1.2.2" class="post green"></div>
<div id="1.2.3" class="post green"></div>
</div>
</div>
<div id="2" class="post blue" data-attr="INVESTMENT_ACCOUNT.accountNameLabel"></div>
<div id="3" class="post blue flex flex-row flex-wrap" data-attr="INVESTMENT_ACCOUNT.accountNameLabel">
<div id="3.1" class="post yellow flex flex-row flex-wrap">
<div id="3.1.1" class="post green"></div>
<div id="3.1.2" class="post green"></div>
<div id="3.1.3" class="post green"></div>
</div>
</div>
<div id="4" class="post blue flex flex-row flex-wrap" data-attr="INVESTMENT_ACCOUNT.accountNameLabel">
<div id="4.1" class="post yellow flex flex-row flex-wrap">
<div id="4.1.1" class="post green"></div>
<div id="4.1.2" class="post green"></div>
<div id="4.1.3" class="post green"></div>
</div>
<div id="4.2" class="post yellow flex flex-row flex-wrap">
<div id="4.2.1" class="post green"></div>
<div id="4.2.2" class="post green"></div>
<div id="4.2.3" class="post green"></div>
</div>
</div>
<div id="5" class="post blue" data-attr="INVESTMENT_ACCOUNT.accountNameLabel"></div>
<div id="6" class="post blue flex flex-row flex-wrap" data-attr="INVESTMENT_ACCOUNT.accountNameLabel">
<div id="6.1" class="post yellow">
<div id="6.1.1" class="post green"></div>
<div...
CSS
* {
box-sizing: border-box;
}
body {
font: 16px 'Helvetica Neue', sans-serif;
}
.context-menu {
/* position: absolute; */
z-index: 1000;
background: #fff;
border: 1px solid #ccc;
box-shadow: 5px 2px 2px gray;
color: #000;
padding: 0.3rem;
max-width: 10rem;
text-align: center;
}
.collapse {
display: none;
}
.items {
list-style: none;
padding: 0.2rem 0.2rem;
margin: 0;
}
.item {
padding: 0.3rem 0;
border-bottom: 1px solid #c0c0c0;
}
.item:hover {
border-bottom: 4px solid #b54637;
}
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.flex-wrap {
flex-wrap: wrap
}
.post {
width: 250px;
height: 250px;
margin: 10px;
}
.blue {
background: orange;
color: white
}
.green {
width: 20px;
height: 20px;
background: yellowgreen;
color: white;
}
.yellow {
width: 100px;
height: 100px;
background: yellow;
color: black;
}
.selected {
box-shadow: 5px 2px 2px red;
}
JavaScript
var ctxMenu = document.querySelector('.context-menu');
var Component = (function() {
var selectedElement;
var selectedComponent;
var getComponentName = function(node) {
if (node.dataset && node.dataset.attr) return node.dataset.attr;
else getComponentName(node.parentNode)
};
return {
setSelected: function() {
var arr = document.querySelectorAll(':hover');
selectedElement = arr.length ? arr[arr.length - 1]: undefined;
selectedComponent = getComponentName(selectedElement);
},
getSelected: function() {
return selectedElement;
},
getName: function() {
return selectedComponent;
}
};
})();
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
e.stopPropagation();
ctxMenu.style.top = '' + e.offsetY + 'px';
ctxMenu.style.left = '' + e.offsetX + 'px';
Component.setSelected();
Component.getSelected().classList.add('selected');
//console.log(document.querySelectorAll( ":hover" ));
//console.log('before:', comp.getSelected());
ctxMenu.classList.remove('collapse');
})
ctxMenu.addEventListener('mouseleave', function() {
ctxMenu.classList.add('collapse');
Component.getSelected().classList.remove('selected');
})
ctxMenu.addEventListener('click', function(e) {
//console.log(e.target.id);
//console.log('current Mouse pos', e.offsetX, e.offsetY);
console.log(e.target.id, " component:", Component.getSelected());
console.log(e.target.id, " component:", Component.getName());
})