Add context menu functionality and styles; refactor main-view.php and layout files
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1048,6 +1048,18 @@ input[type="checkbox"] {
|
|||||||
grid-template-columns: 200px 1fr 300px;
|
grid-template-columns: 200px 1fr 300px;
|
||||||
padding-top: 25px;
|
padding-top: 25px;
|
||||||
|
|
||||||
|
.manage-menu {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 300;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Chris Board - Boardies IT Solutons
|
|
||||||
* @description Creates a 3-dot context menu on tables, <p> tags and heading tags (e.g. h1, h2 etc).
|
|
||||||
* @copyright (c) Boardies IT Solutions - December 2017
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(document).mouseup(function (e) {
|
|
||||||
var div = $(".context-menu-container");
|
|
||||||
if (!div.is(e.target) && div.has(e.target).length === 0)
|
|
||||||
{
|
|
||||||
div.hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function ContextMenu(contextContainerID, menuItemClickCallback)
|
|
||||||
{
|
|
||||||
this.contextMenuContainer = $('.context-menu[data-container-id="'+contextContainerID+'"]');
|
|
||||||
|
|
||||||
this.contextMenuContainer.click(function(e){
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
var parent = $(this);
|
|
||||||
|
|
||||||
//var menuPos = $(this).offset();
|
|
||||||
|
|
||||||
//Show hide the context menu
|
|
||||||
var contextMenuID = "#" + $(this).attr("data-container-id");
|
|
||||||
var contextMenu = $(contextMenuID);
|
|
||||||
|
|
||||||
|
|
||||||
//Use e.clientX get the cursor position and subtract the context menu width so that it appears on the left of
|
|
||||||
//the cursor, minus another 15 take the extra padding into account so the menu doesn't appear
|
|
||||||
//directly under the cursor
|
|
||||||
var menuPos = {left: e.clientX - contextMenu.width() - 15, top: contextMenu.offset().top + e.clientY};
|
|
||||||
|
|
||||||
if (!isElementInViewport(contextMenu)) {
|
|
||||||
alert("View not visible");
|
|
||||||
var rightEdgePos = contextMenu.width() + contextMenu.offset().left;
|
|
||||||
var screenWidth = $(window).width();
|
|
||||||
|
|
||||||
|
|
||||||
var leftShiftOver = menuPos.left - (screenWidth - rightEdgePos);
|
|
||||||
var showPos = menuPos.left - leftShiftOver - 10; //Subtract an extra 10 so it has some margin space
|
|
||||||
|
|
||||||
contextMenu.css({top: '5px', right: "15px", position: 'absolute'});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
contextMenu.css({top: '5px', right: "15px", position: 'absolute'});
|
|
||||||
}
|
|
||||||
|
|
||||||
contextMenu.find("ul > li").click(function(){
|
|
||||||
menuItemClickCallback($(this), parent);
|
|
||||||
contextMenu.hide();
|
|
||||||
|
|
||||||
//Remove the click event otherwise a new one keep getting created, so an additional call event will be called
|
|
||||||
//each time the menu opens and closes
|
|
||||||
contextMenu.find("ul > li").unbind("click");
|
|
||||||
});
|
|
||||||
contextMenu.show();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
this.destroy = function() {
|
|
||||||
this.contextMenuContainer.unbind("click");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function isElementInViewport (el) {
|
|
||||||
|
|
||||||
//special bonus for those using jQuery
|
|
||||||
if (typeof jQuery === "function" && el instanceof jQuery) {
|
|
||||||
el = el[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
var rect = el.getBoundingClientRect();
|
|
||||||
|
|
||||||
return (
|
|
||||||
rect.top >= 0 &&
|
|
||||||
rect.left >= 0 &&
|
|
||||||
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
|
|
||||||
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
|
|
||||||
);
|
|
||||||
}
|
|
||||||
95
libraries/jquery.contextMenu/context-menu.css
Normal file
95
libraries/jquery.contextMenu/context-menu.css
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* @author Chris Board - Boardies IT Solutons
|
||||||
|
* @description Creates a 3-dot context menu on tables, <p> tags and heading tags (e.g. h1, h2 etc).
|
||||||
|
* @copyright (c) Boardies IT Solutions - December 2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
.context-menu,
|
||||||
|
td.context-menu,
|
||||||
|
p.context-menu,
|
||||||
|
h1.context-menu,
|
||||||
|
h2.context-menu,
|
||||||
|
h3.context-menu,
|
||||||
|
h4.context-menu,
|
||||||
|
h5.context-menu {
|
||||||
|
cursor: pointer;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu:after {
|
||||||
|
content: '\2807';
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
cursor: hand;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.context-menu:after {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.contextMenu:after>span {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.context-menu:after,
|
||||||
|
h2.context-menu:after,
|
||||||
|
h3.context-menu:after,
|
||||||
|
h4.context-menu:after,
|
||||||
|
h5.context-menu:after {
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container {
|
||||||
|
background-color: white;
|
||||||
|
z-index: 1000 !important;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
border: solid thin #c4c4c4;
|
||||||
|
padding: 3px;
|
||||||
|
-webkit-box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, 0.18);
|
||||||
|
-moz-box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, 0.18);
|
||||||
|
box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, 0.18);
|
||||||
|
min-width: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li {
|
||||||
|
padding: 5px;
|
||||||
|
cursor: hand;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li.disabled {
|
||||||
|
color: #b7b7b7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li.disabled:hover {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li:hover {
|
||||||
|
background-color: #c4c4c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li.danger:hover {
|
||||||
|
background-color: #ff6959;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li.warning:hover {
|
||||||
|
background-color: #fff27c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-container>ul>li.danger.disabled:hover,
|
||||||
|
.context-menu-container>ul>li.warning.disabled:hover {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
175
libraries/jquery.contextMenu/context-menu.js
Normal file
175
libraries/jquery.contextMenu/context-menu.js
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/**
|
||||||
|
* @author Chris Board - Boardies IT Solutons
|
||||||
|
* @description Creates a 3-dot context menu on tables, <p> tags and heading tags (e.g. h1, h2 etc).
|
||||||
|
* @copyright (c) Boardies IT Solutions - December 2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(document).mouseup(function (e) {
|
||||||
|
var div = $(".context-menu-container");
|
||||||
|
if (!div.is(e.target) && div.has(e.target).length === 0)
|
||||||
|
{
|
||||||
|
div.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function ContextMenu(contextContainerID, menuItemClickCallback, options)
|
||||||
|
{
|
||||||
|
this.contextContainerID = contextContainerID;
|
||||||
|
this.contextMenuContainer = $('.context-menu[data-container-id="'+contextContainerID+'"]');
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.contextMenuContainer.click(function(e){
|
||||||
|
var parent = $(this);
|
||||||
|
|
||||||
|
|
||||||
|
//var menuPos = $(this).offset();
|
||||||
|
|
||||||
|
//Show hide the context menu
|
||||||
|
var contextMenuID = "#" + $(this).attr("data-container-id");
|
||||||
|
var contextMenu = $(contextMenuID);
|
||||||
|
self.contextMenu = contextMenu;
|
||||||
|
|
||||||
|
|
||||||
|
//Use e.clientX get the cursor position and subtract the context menu width so that it appears on the left of
|
||||||
|
//the cursor, minus another 15 take the extra padding into account so the menu doesn't appear
|
||||||
|
//directly under the cursor
|
||||||
|
var menuPos = {left: e.clientX - contextMenu.width() - 15, top: contextMenu.offset().top + e.clientY};
|
||||||
|
|
||||||
|
if (!isElementInViewport(contextMenu)) {
|
||||||
|
alert("View not visible");
|
||||||
|
var rightEdgePos = contextMenu.width() + contextMenu.offset().left;
|
||||||
|
var screenWidth = $(window).width();
|
||||||
|
|
||||||
|
|
||||||
|
var leftShiftOver = menuPos.left - (screenWidth - rightEdgePos);
|
||||||
|
var showPos = menuPos.left - leftShiftOver - 10; //Subtract an extra 10 so it has some margin space
|
||||||
|
|
||||||
|
contextMenu.css({top: menuPos.top, left: showPos, position: 'absolute'});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
contextMenu.css({top: menuPos.top, left: menuPos.left, position: 'absolute'});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options != null && typeof options !== "undefined" )
|
||||||
|
{
|
||||||
|
if (typeof options.openCallBack !== "undefined")
|
||||||
|
{
|
||||||
|
options.openCallBack(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMenu.find("ul > li").click(function(){
|
||||||
|
if (!$(this).hasClass("disabled")) {
|
||||||
|
menuItemClickCallback($(this), parent);
|
||||||
|
contextMenu.hide();
|
||||||
|
|
||||||
|
//Remove the click event otherwise a new one keep getting created, so an additional call event will be called
|
||||||
|
//each time the menu opens and closes
|
||||||
|
contextMenu.find("ul > li").unbind("click");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
contextMenu.show();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.destroy = function() {
|
||||||
|
this.contextMenuContainer.unbind("click");
|
||||||
|
};
|
||||||
|
|
||||||
|
this.returnContextMenu = function(){
|
||||||
|
var contextMenu = null;
|
||||||
|
if (typeof self.contextMenu !== "undefined")
|
||||||
|
{
|
||||||
|
contextMenu = self.contextMenu;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var contextMenuContainer = $('.context-menu[data-container-id="'+this.contextContainerID+'"]');
|
||||||
|
var contextMenuID = "#" + contextMenuContainer.attr("data-container-id");
|
||||||
|
contextMenu = $(contextMenuID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contextMenu;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.disableMenuItem = function(item){
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
var contextMenu = this.returnContextMenu();
|
||||||
|
|
||||||
|
|
||||||
|
var itemCounter = contextMenu.find("ul > li").length;
|
||||||
|
contextMenu.find("ul > li").each(function(){
|
||||||
|
if (typeof item === "number")
|
||||||
|
{
|
||||||
|
if (item < 0 || item > itemCounter)
|
||||||
|
{
|
||||||
|
throw "3Dot-ContextMenu: Item index is out of bounds";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count === item)
|
||||||
|
{
|
||||||
|
$(this).addClass("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (typeof item === "string")
|
||||||
|
{
|
||||||
|
if ($(this).text() === item)
|
||||||
|
{
|
||||||
|
$(this).addClass("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.enableMenuItem = function(item){
|
||||||
|
var count = 0;
|
||||||
|
var contextMenu = this.returnContextMenu();
|
||||||
|
var itemCount = contextMenu.find("ul > li").length;
|
||||||
|
|
||||||
|
contextMenu.find("ul > li").each(function(){
|
||||||
|
if (typeof item === "number")
|
||||||
|
{
|
||||||
|
if (item < 0 || item > itemCount)
|
||||||
|
{
|
||||||
|
throw "3Dot-ContextMenu: Item index is out of bounds";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count === item)
|
||||||
|
{
|
||||||
|
$(this).removeClass("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (typeof item === "string")
|
||||||
|
{
|
||||||
|
if ($(this).text() === item)
|
||||||
|
{
|
||||||
|
$(this).removeClass("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElementInViewport (el) {
|
||||||
|
|
||||||
|
//special bonus for those using jQuery
|
||||||
|
if (typeof jQuery === "function" && el instanceof jQuery) {
|
||||||
|
el = el[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
var rect = el.getBoundingClientRect();
|
||||||
|
|
||||||
|
return (
|
||||||
|
rect.top >= 0 &&
|
||||||
|
rect.left >= 0 &&
|
||||||
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
|
||||||
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -141,6 +141,7 @@
|
|||||||
$( function()
|
$( function()
|
||||||
{
|
{
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
console.log('test');
|
||||||
var tableContextMenu = new ContextMenu("category-<?= $category['id'];?>-menu", menuItemClickListener);
|
var tableContextMenu = new ContextMenu("category-<?= $category['id'];?>-menu", menuItemClickListener);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -290,7 +291,6 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="/libraries/context-menu.js"></script>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function menuItemClickListener(menu_item, parent) {}
|
function menuItemClickListener(menu_item, parent) {}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
|
||||||
<script type="text/javascript" src="/libraries/framework/vendor/jquery/jquery_ui/jquery-ui.min.js"></script>
|
<script type="text/javascript" src="/libraries/framework/vendor/jquery/jquery_ui/jquery-ui.min.js"></script>
|
||||||
<script type="text/javascript" src="/libraries/framework/vendor/plugins/datepicker/js/bootstrap-datetimepicker.js"></script>
|
<script type="text/javascript" src="/libraries/framework/vendor/plugins/datepicker/js/bootstrap-datetimepicker.js"></script>
|
||||||
<script type="text/javascript" src="/libraries/framework/vendor/plugins/daterange/daterangepicker.js"></script>
|
<script type="text/javascript" src="/libraries/framework/vendor/plugins/daterange/daterangepicker.js"></script>
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
<script type="text/javascript" src="/libraries/daterange/daterangepicker.js"></script>
|
<script type="text/javascript" src="/libraries/daterange/daterangepicker.js"></script>
|
||||||
<script type="text/javascript" src="/libraries/jquery-confirm/jquery-confirm.min.js"></script>
|
<script type="text/javascript" src="/libraries/jquery-confirm/jquery-confirm.min.js"></script>
|
||||||
<script type="text/javascript" src="/libraries/select2/js/select2.full.min.js"></script>
|
<script type="text/javascript" src="/libraries/select2/js/select2.full.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/libraries/jquery.contextMenu/context-menu.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
<link rel="Stylesheet" type="text/css" href="/libraries/framework/vendor/jquery/jquery_ui/jquery-ui.structure.min.css">
|
<link rel="Stylesheet" type="text/css" href="/libraries/framework/vendor/jquery/jquery_ui/jquery-ui.structure.min.css">
|
||||||
<link rel="Stylesheet" type="text/css" href="/libraries/framework/vendor/jquery/jquery_ui/jquery-ui.theme.min.css">
|
<link rel="Stylesheet" type="text/css" href="/libraries/framework/vendor/jquery/jquery_ui/jquery-ui.theme.min.css">
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/libraries/jquery-confirm/jquery-confirm.min.css">
|
<link rel="stylesheet" type="text/css" href="/libraries/jquery-confirm/jquery-confirm.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/libraries/select2/css/select2.min.css">
|
<link rel="stylesheet" type="text/css" href="/libraries/select2/css/select2.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/libraries/select2/css/select2-bootstrap-5-theme.min.css">
|
<link rel="stylesheet" type="text/css" href="/libraries/select2/css/select2-bootstrap-5-theme.min.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/libraries/jquery.contextMenu/context-menu.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="logged">
|
<body class="logged">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
|
|||||||
Reference in New Issue
Block a user