From d730c6a12fc6ecbeddf12255c81367a423d70310 Mon Sep 17 00:00:00 2001 From: t71rs <166131967+t71rs@users.noreply.github.com> Date: Tue, 30 Apr 2024 19:02:12 +0200 Subject: [PATCH] Arrow key support signing (#1143) * Added Arrow Key functionality for the Sign page. * Added Arrow Key functionality for the Sign page. * Adjusted step size, so it is relative to the size of the draggable * Enabled Arrow Key support also for Add-Image --------- Co-authored-by: Eric <71648843+sbplat@users.noreply.github.com> --- .../resources/static/js/draggable-utils.js | 170 ++++++++++++------ 1 file changed, 120 insertions(+), 50 deletions(-) diff --git a/src/main/resources/static/js/draggable-utils.js b/src/main/resources/static/js/draggable-utils.js index bff4c3d4..6064e398 100644 --- a/src/main/resources/static/js/draggable-utils.js +++ b/src/main/resources/static/js/draggable-utils.js @@ -5,74 +5,130 @@ const DraggableUtils = { pdfDoc: null, pageIndex: 0, documentsMap: new Map(), + lastInteracted: null, init() { interact(".draggable-canvas") - .draggable({ - listeners: { - move: (event) => { - const target = event.target; - const x = (parseFloat(target.getAttribute("data-bs-x")) || 0) + event.dx; - const y = (parseFloat(target.getAttribute("data-bs-y")) || 0) + event.dy; + .draggable({ + listeners: { + move: (event) => { + const target = event.target; + const x = (parseFloat(target.getAttribute("data-bs-x")) || 0) + + event.dx; + const y = (parseFloat(target.getAttribute("data-bs-y")) || 0) + + event.dy; - target.style.transform = `translate(${x}px, ${y}px)`; - target.setAttribute("data-bs-x", x); - target.setAttribute("data-bs-y", y); + target.style.transform = `translate(${x}px, ${y}px)`; + target.setAttribute("data-bs-x", x); + target.setAttribute("data-bs-y", y); - this.onInteraction(target); - }, + this.onInteraction(target); + //update the last interacted element + this.lastInteracted = event.target; }, - }) - .resizable({ - edges: { left: true, right: true, bottom: true, top: true }, - listeners: { - move: (event) => { - var target = event.target; - var x = parseFloat(target.getAttribute("data-bs-x")) || 0; - var y = parseFloat(target.getAttribute("data-bs-y")) || 0; + }, + }) + .resizable({ + edges: { left: true, right: true, bottom: true, top: true }, + listeners: { + move: (event) => { + var target = event.target; + var x = parseFloat(target.getAttribute("data-bs-x")) || 0; + var y = parseFloat(target.getAttribute("data-bs-y")) || 0; - // check if control key is pressed - if (event.ctrlKey) { - const aspectRatio = target.offsetWidth / target.offsetHeight; - // preserve aspect ratio - let width = event.rect.width; - let height = event.rect.height; + // check if control key is pressed + if (event.ctrlKey) { + const aspectRatio = target.offsetWidth / target.offsetHeight; + // preserve aspect ratio + let width = event.rect.width; + let height = event.rect.height; - if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) { - height = width / aspectRatio; - } else { - width = height * aspectRatio; - } - - event.rect.width = width; - event.rect.height = height; + if (Math.abs(event.deltaRect.width) >= Math.abs( + event.deltaRect.height)) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; } - target.style.width = event.rect.width + "px"; - target.style.height = event.rect.height + "px"; + event.rect.width = width; + event.rect.height = height; + } - // translate when resizing from top or left edges - x += event.deltaRect.left; - y += event.deltaRect.top; + target.style.width = event.rect.width + "px"; + target.style.height = event.rect.height + "px"; - target.style.transform = "translate(" + x + "px," + y + "px)"; + // translate when resizing from top or left edges + x += event.deltaRect.left; + y += event.deltaRect.top; - target.setAttribute("data-bs-x", x); - target.setAttribute("data-bs-y", y); - target.textContent = Math.round(event.rect.width) + "\u00D7" + Math.round(event.rect.height); + target.style.transform = "translate(" + x + "px," + y + "px)"; - this.onInteraction(target); - }, + target.setAttribute("data-bs-x", x); + target.setAttribute("data-bs-y", y); + target.textContent = Math.round(event.rect.width) + "\u00D7" + + Math.round(event.rect.height); + + this.onInteraction(target); }, + }, - modifiers: [ - interact.modifiers.restrictSize({ - min: { width: 5, height: 5 }, - }), - ], - inertia: true, + modifiers: [ + interact.modifiers.restrictSize({ + min: {width: 5, height: 5}, + }), + ], + inertia: true, + }); + //Arrow key Support for Add-Image and Sign pages + if(window.location.pathname.endsWith('sign') || window.location.pathname.endsWith('add-image')) { + window.addEventListener('keydown', (event) => { + //Check for last interacted element + if (!this.lastInteracted){ + return; + } + // Get the currently selected element + const target = this.lastInteracted; + + // Step size relatively to the elements size + const stepX = target.offsetWidth * 0.05; + const stepY = target.offsetHeight * 0.05; + + // Get the current x and y coordinates + let x = (parseFloat(target.getAttribute('data-bs-x')) || 0); + let y = (parseFloat(target.getAttribute('data-bs-y')) || 0); + + // Check which key was pressed and update the coordinates accordingly + switch (event.key) { + case 'ArrowUp': + y -= stepY; + event.preventDefault(); // Prevent the default action + break; + case 'ArrowDown': + y += stepY; + event.preventDefault(); + break; + case 'ArrowLeft': + x -= stepX; + event.preventDefault(); + break; + case 'ArrowRight': + x += stepX; + event.preventDefault(); + break; + default: + return; // Listen only to arrow keys + } + + // Update position + target.style.transform = `translate(${x}px, ${y}px)`; + target.setAttribute('data-bs-x', x); + target.setAttribute('data-bs-y', y); + + DraggableUtils.onInteraction(target); }); + } }, + onInteraction(target) { this.boxDragContainer.appendChild(target); }, @@ -88,9 +144,18 @@ const DraggableUtils = { createdCanvas.setAttribute("data-bs-x", x); createdCanvas.setAttribute("data-bs-y", y); + //Click element in order to enable arrow keys + createdCanvas.addEventListener('click', () => { + this.lastInteracted = createdCanvas; + }); + createdCanvas.onclick = (e) => this.onInteraction(e.target); this.boxDragContainer.appendChild(createdCanvas); + + //Enable Arrow keys directly after the element is created + this.lastInteracted = createdCanvas; + return createdCanvas; }, createDraggableCanvasFromUrl(dataUrl) { @@ -134,6 +199,11 @@ const DraggableUtils = { }, deleteDraggableCanvas(element) { if (element) { + //Check if deleted element is the last interacted + if (this.lastInteracted === element) { + // If it is, set lastInteracted to null + this.lastInteracted = null; + } element.remove(); } },