aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/static/map.js
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/static/map.js')
-rw-r--r--internal/admin/static/map.js80
1 files changed, 64 insertions, 16 deletions
diff --git a/internal/admin/static/map.js b/internal/admin/static/map.js
index f89a434..47dcb27 100644
--- a/internal/admin/static/map.js
+++ b/internal/admin/static/map.js
@@ -6,6 +6,7 @@ var dragRoom = false;
var linkDrag = false, linkFromId = null, linkTargetId = null, linkGhostDir = null;
var linkDragOneWay = false;
var shiftHeld = false;
+var delOneWay = false;
var delDrag = false, delFromId = null, delTargetId = null;
var roomMap = {}, occupied = {};
var dirChangedByUser = false;
@@ -21,12 +22,21 @@ var upTarget = {}, downTarget = {};
var _mapMouseCleanup = false;
+function isShiftKey(e) {
+ return e && (e.key === 'Shift' || e.code === 'ShiftLeft' || e.code === 'ShiftRight' || e.keyCode === 16);
+}
+
function onMapMouseMove(e) {
if (!dragging) return;
var moved = Math.abs(e.clientX - startX) >= 4 || Math.abs(e.clientY - startY) >= 4;
if (delFromId && moved && !delDrag) { delDrag = true; }
- if (delDrag && moved) { updateDelDragTarget(e); return; }
+ if (delDrag && moved) {
+ delOneWay = e.shiftKey;
+ updateDelDragTarget(e);
+ showDelDragBadge();
+ return;
+ }
if (!dragRoom && !delDrag && !delFromId) {
panX += e.clientX - prevX;
@@ -37,7 +47,8 @@ function onMapMouseMove(e) {
if (linkFromId && moved) {
linkDrag = true;
- showDragBadge(linkDragOneWay ? 'One-way link' : 'Two-way link');
+ linkDragOneWay = e.shiftKey;
+ showLinkDragBadge();
updateLinkDragTarget(e);
}
}
@@ -54,24 +65,28 @@ function onMapMouseUp(e) {
showRoomContextMenu(startX, startY, delFromId);
clearDelHighlight();
dragging = false; dragRoom = false; delFromId = null; delTargetId = null; delDrag = false;
+ if (document.activeElement && document.activeElement.blur) document.activeElement.blur();
return;
}
if (delDrag && delFromId && delTargetId) {
- deleteLink(delFromId, delTargetId);
+ deleteLink(delFromId, delTargetId, (delOneWay || e.shiftKey) ? 'from' : '');
clearDelHighlight();
- dragging = false; dragRoom = false; delDrag = false; delFromId = null; delTargetId = null;
+ hideDragBadge();
+ dragging = false; dragRoom = false; delDrag = false; delFromId = null; delTargetId = null; delOneWay = false;
+ if (document.activeElement && document.activeElement.blur) document.activeElement.blur();
return;
}
if (linkDrag && linkFromId) {
- if (linkTargetId) { createLink(linkFromId, linkTargetId, linkDragOneWay); }
- else if (linkGhostDir) { createRoom(linkFromId, linkGhostDir); }
+ var oneway = linkDragOneWay || e.shiftKey;
+ if (linkTargetId) { createLink(linkFromId, linkTargetId, oneway); }
+ else if (linkGhostDir) { createRoom(linkFromId, linkGhostDir, oneway); }
} else if (!moved && !delDrag) {
if (e.target.classList.contains('rm')) {
selectRoom(parseInt(e.target.getAttribute('data-id')));
} else if (e.target.classList.contains('ghost')) {
- createRoom(selectedRoom, e.target.getAttribute('data-dir'));
+ createRoom(selectedRoom, e.target.getAttribute('data-dir'), e.shiftKey);
}
}
@@ -80,7 +95,8 @@ function onMapMouseUp(e) {
hideDragBadge();
dragging = false; dragRoom = false;
linkDrag = false; linkFromId = null; linkTargetId = null; linkGhostDir = null; linkDragOneWay = false;
- delDrag = false; delFromId = null; delTargetId = null;
+ delDrag = false; delFromId = null; delTargetId = null; delOneWay = false;
+ if (document.activeElement && document.activeElement.blur) document.activeElement.blur();
}
function cancelMapDrag() {
@@ -93,14 +109,15 @@ function cancelMapDrag() {
hideDragBadge();
dragging = false; dragRoom = false;
linkDrag = false; linkFromId = null; linkTargetId = null; linkGhostDir = null; linkDragOneWay = false;
- delDrag = false; delFromId = null; delTargetId = null;
+ delDrag = false; delFromId = null; delTargetId = null; delOneWay = false;
+ if (document.activeElement && document.activeElement.blur) document.activeElement.blur();
}
-function showDragBadge(text) {
+function showDragBadge(text, oneway) {
var badge = document.getElementById('linkModeBadge');
if (!badge) return;
badge.textContent = text;
- badge.className = 'link-mode-badge' + (linkDragOneWay ? ' oneway' : '');
+ badge.className = 'link-mode-badge' + (oneway ? ' oneway' : '');
badge.style.display = '';
}
@@ -109,6 +126,24 @@ function hideDragBadge() {
if (badge) badge.style.display = 'none';
}
+function showLinkDragBadge() {
+ var label = linkDragOneWay ? 'One way link' : 'Two-way link';
+ var toLabel = linkTargetId ? linkTargetId : (linkGhostDir ? 'new' : null);
+ if (linkFromId && toLabel) label += ' (#' + linkFromId + ' to #' + toLabel + ')';
+ showDragBadge(label, linkDragOneWay);
+}
+
+function showDelDragBadge() {
+ var label = delOneWay ? 'One way remove' : 'Two-way remove';
+ if (delFromId && delTargetId) label += ' (#' + delFromId + ' to #' + delTargetId + ')';
+ showDragBadge(label, delOneWay);
+}
+
+function refreshDragMode(shiftDown) {
+ if (linkDrag && linkFromId) { linkDragOneWay = shiftDown; showLinkDragBadge(); }
+ if (delDrag && delFromId) { delOneWay = shiftDown; showDelDragBadge(); }
+}
+
function changeZ(dz) {
if (dz === 0) currentZ = 0; else currentZ += dz;
panX = 0; panY = 0; scale = 1;
@@ -279,6 +314,17 @@ function renderMap(data) {
svg.oncontextmenu = function(e) { e.preventDefault(); };
+ if (!svg._mapKeysWired) {
+ svg.setAttribute('tabindex', '0');
+ svg.addEventListener('keydown', function(e) {
+ if (isShiftKey(e)) { shiftHeld = true; if (dragging) refreshDragMode(true); }
+ });
+ svg.addEventListener('keyup', function(e) {
+ if (isShiftKey(e)) { shiftHeld = false; if (dragging) refreshDragMode(false); }
+ });
+ svg._mapKeysWired = true;
+ }
+
svg.onmousedown = function(e) {
var onRoom = e.target.classList.contains('rm');
var onGhost = e.target.classList.contains('ghost');
@@ -296,8 +342,9 @@ function renderMap(data) {
if (e.button === 2 && onRoom) {
delFromId = parseInt(e.target.getAttribute('data-id'));
- delDrag = false; delTargetId = null;
+ delDrag = false; delTargetId = null; delOneWay = false;
dragging = true;
+ if (svg.focus) svg.focus();
startX = e.clientX; startY = e.clientY;
prevX = e.clientX; prevY = e.clientY;
dragRoom = true; linkFromId = null; linkDrag = false; linkTargetId = null; linkGhostDir = null;
@@ -317,9 +364,9 @@ function renderMap(data) {
return;
}
- e.preventDefault();
dragRoom = onRoom || onGhost;
dragging = true;
+ if (svg.focus) svg.focus();
startX = e.clientX; startY = e.clientY;
prevX = e.clientX; prevY = e.clientY;
linkFromId = onRoom ? parseInt(e.target.getAttribute('data-id')) : null;
@@ -1863,11 +1910,12 @@ function deleteRoom(id) {
}).catch(function(e) { notify('Delete failed: ' + e.message, 'error'); });
}
-function createRoom(fromID, dir) {
+function createRoom(fromID, dir, oneway) {
API.get('/api/next-room-id?from=' + fromID).then(function(r) {
var newID = r.id;
var name = 'Room #' + newID;
var body = { name: name, link_from: fromID, link_dir: dir };
+ if (oneway) body.link_oneway = true;
var srcRoom = roomMap[fromID];
if (srcRoom && srcRoom.color) body.color = srcRoom.color;
API.post('/api/rooms', body).then(function(resp) {
@@ -2395,6 +2443,6 @@ function reloadRoomDirs(cb) {
}
document.addEventListener('DOMContentLoaded', function() { loadRoomDirs(function() { loadMap(); }); initPanelResize();
- document.addEventListener('keydown', function(e) { if (e.key === 'Shift') shiftHeld = true; });
- document.addEventListener('keyup', function(e) { if (e.key === 'Shift') shiftHeld = false; });
+ window.addEventListener('keydown', function(e) { if (isShiftKey(e)) { shiftHeld = true; if (dragging) refreshDragMode(true); } });
+ window.addEventListener('keyup', function(e) { if (isShiftKey(e)) { shiftHeld = false; if (dragging) refreshDragMode(false); } });
});