Improved internals of web app content menu system.
Ylian Saint-Hilaire committed
Feb 17, 2020 at 13:41 UTC
40c6cdc88a6a665498f70b978ad531a4f98d03f7
1 file changed
+48
-57
views/default.handlebars
+48
-57
@@ -606,7 +606,7 @@
606
<div>
607
<div id="idx_termFullBtn2" onclick=deskToggleFull(event)> ✖</div>
608
<input type="button" id="autoconnectbutton2" value="AutoConnect" onclick=autoConnectTerminal(event) onkeypress="return false" onkeydown="return false" style="display:none" />
609
- <span id="connectbutton2span"><input type="button" id="connectbutton2" value="Connect" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
609
+ <span id="connectbutton2span"><input type="button" id="connectbutton2" cmenu="termConnectButton" value="Connect" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
610
<span id="connectbutton2hspan"> <input type="button" id="connectbutton2h" value="HW Connect" title="Connect using Intel AMT hardware KVM" onclick=connectTerminal(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
611
<span id="disconnectbutton2span"> <input type="button" id="disconnectbutton2" value="Disconnect" onclick=connectTerminal(event,0) onkeypress="return false" onkeydown="return false" /></span>
612
<span id="termstatus">Disconnected</span><span id="termtitle"></span>
@@ -3018,7 +3018,7 @@
3018
var collapsed = CollapsedGroups[node.meshid];
3019
r += '<img class=collapseImage id=\"DevxColImg' + deviceHeaderId + '\" src=images/c' + ((collapsed === true)?'1':'2') + '.png height=8 width=8 style=margin-left:2px;margin-right:2px;cursor:pointer onclick=toggleCollapseGroup(\"' + deviceHeaderId + '\",\"' + node.meshid + '\",' + view + ')></img>'; // Collapse action
3020
}
3021
- r += '<span id=MxMESH tabindex=0 style=cursor:pointer onclick=gotoMesh("' + node.meshid + '") onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + node.meshid + '\')">' + EscapeHtml(meshes[node.meshid].name) + '</span>' + getMeshActions(mesh2, meshrights) + '</div>';
3021
+ r += '<span id=MxMESH cmenu=meshContextMenu tabindex=0 style=cursor:pointer onclick=gotoMesh("' + node.meshid + '") onkeypress="if (event.key==\'Enter\') gotoMesh(\'' + node.meshid + '\')">' + EscapeHtml(meshes[node.meshid].name) + '</span>' + getMeshActions(mesh2, meshrights) + '</div>';
3022
if (view == 2) { r += '</div>'; }
3023
current = node.meshid;
3024
displayedMeshes[current] = 1;
@@ -3062,7 +3062,7 @@
3062
var icon = node.icon;
3063
if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
3064
if (view == 1) {
3065
- r += '<div id=devs onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div></div>';
3065
+ r += '<div id=devs cmenu=devsContentMenu onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div></div>';
3066
} else if (view == 2) {
3067
var states = [];
3068
if (node.conn) {
@@ -3999,65 +3999,56 @@
3999
4000
var contextelement = null;
4001
function handleContextMenu(event) {
4002
+ // When called, we look for elements with "cmenu=xxx" and show the right context menu for that element.
4003
hideContextMenu();
4004
var scrollLeft = (window.pageXOffset !== null) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
4005
var scrollTop = (window.pageYOffset !== null) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
4006
var elem = document.elementFromPoint(event.pageX - scrollLeft, event.pageY - scrollTop);
4006
- //console.log('handleContextMenu', scrollLeft, scrollTop, elem, elem.parentElement, elem.parentElement.parentElement);
4007
-
4008
- // Look for a file entry element
4009
- var fileElement = null, elx = elem;
4010
- while (elx && elx != null && elx.id != 'fileEntry') { elx = elx.parentElement; }
4011
- if (elx && (elx.id == 'fileEntry')) { fileElement = elx; }
4012
-
4013
- if (elem && elem != null && elem.id == 'rdpClickOnceLink' && currentNode && currentNode.agent && (currentNode.agent.id > 0) && (currentNode.agent.id < 5)) {
4014
- contextelement = elem;
4015
- var contextmenudiv = document.getElementById('altPortContextMenu');
4016
- showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4017
- } else if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 0) && (currentNode.agent.id < 5)) {
4018
- contextelement = elem;
4019
- var contextmenudiv = document.getElementById('termShellContextMenu');
4020
- showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4021
- } else if (elem && elem != null && elem.id == 'connectbutton2' && currentNode && currentNode.agent && (currentNode.agent.id > 4)) {
4022
- contextelement = elem;
4023
- var contextmenudiv = document.getElementById('termShellContextMenuLinux');
4024
- showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4025
- } else if (fileElement && currentNode) {
4026
- contextelement = fileElement;
4027
- var contextmenudiv = document.getElementById('filesContextMenu');
4028
- showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4029
- } else if (elem && elem != null && elem.id == 'MxMESH') {
4030
- contextelement = elem;
4031
- var contextmenudiv = document.getElementById('meshContextMenu');
4032
- showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4033
- /*} else if (elem && elem != null && elem.classList.contains('pluginTab')) {
4007
+ while (elem && elem != null && elem.attributes.cmenu == null) { elem = elem.parentElement; } // Go up until element with context menu or root is reached.
4008
+ if (elem == null) return true; // No "cmenu=xxx" found at the element that was clicked.
4009
+ var cmenu = elem.attributes.cmenu.value;
4010
+
4011
+ switch (cmenu) {
4012
+ case 'termConnectButton': {
4013
+ // Terminal connect button context menu
4014
+ if ((currentNode == null) || (currentNode.agent == null)) return true;
4015
contextelement = elem;
4035
- var contextmenudiv = document.getElementById('pluginTabContextMenu');
4016
+ var contextmenudiv = document.getElementById('termShellContextMenu'); // Windows options (Power Shell)
4017
+ if (currentNode.agent.id > 4) { contextmenudiv = document.getElementById('termShellContextMenuLinux'); } // Non-Windows options
4018
+ showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4019
+ break;
4020
+ }
4021
+ case 'devsContentMenu': {
4022
+ // Device content menu
4023
+ contextelement = elem;
4024
+ var contextmenudiv = document.getElementById('contextMenu');
4025
showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4037
- */
4038
- } else {
4039
- while (elem && elem != null && elem.id != 'devs') { elem = elem.parentElement; }
4040
- if (!elem || elem == null) return true;
4041
- contextelement = elem;
4042
- var contextmenudiv = document.getElementById('contextMenu');
4043
- showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4044
-
4045
- // Get the node and set the menu options
4046
- var nodeid = contextelement.children[1].attributes.onclick.value;
4047
- var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
4048
- var mesh = meshes[node.meshid];
4049
- var rights = GetNodeRights(node);
4050
- var consoleRights = ((rights & 16) != 0);
4051
-
4052
- // Check if we have terminal and file access
4053
- var terminalAccess = ((rights == 0xFFFFFFFF) || ((rights & 512) == 0));
4054
- var fileAccess = ((rights == 0xFFFFFFFF) || ((rights & 1024) == 0));
4026
4056
- QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((rights & 8) || (rights & 256)));
4057
- QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (rights & 8) && terminalAccess);
4058
- QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (rights & 8) && fileAccess);
4059
- QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (rights & 8));
4060
- QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (rights & 8));
4027
+ // Get the node and set the menu options
4028
+ var nodeid = contextelement.children[1].attributes.onclick.value;
4029
+ var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
4030
+ var mesh = meshes[node.meshid];
4031
+ var rights = GetNodeRights(node);
4032
+ var consoleRights = ((rights & 16) != 0);
4033
+
4034
+ // Check if we have terminal and file access
4035
+ var terminalAccess = ((rights == 0xFFFFFFFF) || ((rights & 512) == 0));
4036
+ var fileAccess = ((rights == 0xFFFFFFFF) || ((rights & 1024) == 0));
4037
+
4038
+ QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((rights & 8) || (rights & 256)));
4039
+ QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (rights & 8) && terminalAccess);
4040
+ QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (rights & 8) && fileAccess);
4041
+ QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (rights & 8));
4042
+ QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (rights & 8));
4043
+ break;
4044
+ }
4045
+ default: {
4046
+ // Basic context menu
4047
+ if ((contextmenudiv = document.getElementById(cmenu)) == null) return true;
4048
+ contextelement = elem;
4049
+ showContextMenuDiv(contextmenudiv, event.pageX, event.pageY);
4050
+ break;
4051
+ }
4052
}
4053
return haltEvent(event);
4054
}
@@ -4989,7 +4980,7 @@
4980
4981
// RDP link, show this link only of the remote machine is Windows.
4982
if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
4992
- if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a href=# id=rdpClickOnceLink onclick=p10clickOnce("' + node._id + '","RDP2",3389) title=\"' + "Requires Microsoft ClickOnce support in your browser" + '.\">' + "RDP" + '</a> '; }
4983
+ if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a href=# cmenu=altPortContextMenu id=rdpClickOnceLink onclick=p10clickOnce("' + node._id + '","RDP2",3389) title=\"' + "Requires Microsoft ClickOnce support in your browser" + '.\">' + "RDP" + '</a> '; }
4984
if (node.agent.id > 4) {
4985
x += '<a href=# onclick=p10clickOnce("' + node._id + '","PSSH",22) title=\"' + "Requires Microsoft ClickOnce support in your browser." + '\">' + "Putty" + '</a> ';
4986
x += '<a href=# onclick=p10clickOnce("' + node._id + '","WSCP",22) title=\"' + "Requires Microsoft ClickOnce support in your browser." + '\">' + "WinSCP" + '</a> ';
@@ -6847,7 +6838,7 @@
6838
} else {
6839
var link = shortname;
6840
if (f.s > 0) { link = '<a hrf=# rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"return p13downloadfile(\'' + encodeURIComponent(newlinkpath + '/' + name) + '\',\'' + encodeURIComponent(name) + '\',' + f.s + ')\">' + shortname + '</a>'; }
6850
- h = '<div id=fileEntry fileIndex=' + i + ' class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
6841
+ h = '<div id=fileEntry cmenu=filesContextMenu fileIndex=' + i + ' class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
6842
}
6843
6844
if (f.t < 3) { html1 += h; } else { html2 += h; }