fix bugs in drag/drop, move styling for functions to separate sheets

To clean up the multi tool page and make the pdf adapters more re-usable the style for them was moved to separate pages that are inserted into head when the adapter is created.
This commit is contained in:
jordy 2023-04-30 13:38:30 +02:00
parent 9a1510a4f1
commit b470cdf60c
7 changed files with 276 additions and 191 deletions

View file

@ -0,0 +1,78 @@
#drag-container {
position: fixed;
display:flex;
inset: 0;
pointer-events: none;
z-index: 10000;
visibility: hidden;
}
#drag-container:not(:empty) {
visibility: visible;
}
#drag-container .dragged-img {
position: fixed;
max-width: 200px;
max-height: 200px;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
transform-origin: top left;
}
.drag-manager_dragging {
width: 0px;
visibility: hidden;
}
.drag-manager_draghover {
width: 375px !important;
}
.drag-manager_draghover .insert-file-button-container {
display: none !important;
}
.drag-manager_draghover .button-container {
visibility: hidden !important;
}
html[lang-direction=ltr] .drag-manager_draghover img {
left: calc(50% + 62.5px) !important;
}
html[lang-direction=rtl] .drag-manager_draghover img {
left: unset;
}
.drag-manager_dragging-container .hide-on-drag {
display: none !important;
}
.drag-manager_endpoint {
width: 80px;
height: 100%;
background-color: #FFFFFF10;
transition: width 0.1s;
animation: end-drop-expand .3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.drag-manager_endpoint svg {
width: 50px;
height: 50px;
}
.drag-manager_endpoint.drag-manager_draghover {
width: 150px !important;
}
@keyframes end-drop-expand {
from {
width: 0;
}
to {
width: 80px;
}
}

View file

@ -0,0 +1,40 @@
#image-highlighter {
position: fixed;
display:flex;
inset: 0;
z-index: 10000;
background-color: rgba(0, 0, 0, 0);
visibility: hidden;
align-items: center;
justify-content: center;
transition: visbility 0.1s linear, background-color 0.1s linear;
}
#image-highlighter > * {
max-width: 80vw;
max-height: 80vh;
animation: image-highlight .1s linear;
transition: transform .1s linear, opacity .1s linear;
}
#image-highlighter > *.remove {
transform: scale(0.8) !important;
opacity: 0 !important;
}
#image-highlighter:not(:empty) {
background-color: rgba(0, 0, 0, 0.37);
visibility: visible;
}
@keyframes image-highlight {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}

View file

@ -0,0 +1,87 @@
.pdf-actions_button-container {
z-index: 2;
display:flex;
opacity: 0;
transition: opacity 0.1s linear;
}
.pdf-actions_container:hover .pdf-actions_button-container {
opacity: 1;
}
.pdf-actions_button-container > * {
padding: 0.25rem 0.5rem;
margin: 3px;
display: block;
}
.pdf-actions_container svg {
width: 16px;
height: 16px;
}
.pdf-actions_container:nth-child(1) .pdf-actions_move-left-button {
display: none;
}
.pdf-actions_container:last-child .pdf-actions_move-right-button {
display: none;
}
/* "insert pdf" buttons that appear on the right when hover */
.pdf-actions_insert-file-button-container {
translate: 0 -50%;
width: 80px;
height: 100%;
z-index: 1;
opacity: 0;
transition: opacity 0.2s;
}
.pdf-actions_insert-file-button-container.left {
left: -20px;
}
.pdf-actions_insert-file-button-container.right {
right: -20px;
}
html[lang-direction=ltr] .pdf-actions_insert-file-button-container.right {
display:none;
}
html[lang-direction=rtl] .pdf-actions_insert-file-button-container.left {
display:none;
}
.pdf-actions_insert-file-button-container.left .pdf-actions_insert-file-button {
left: 0;
translate: 0 -50%;
}
.pdf-actions_insert-file-button-container.right .pdf-actions_insert-file-button {
right: 0;
translate: 0 -50%;
}
html[lang-direction=ltr] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right {
display: block;
}
html[lang-direction=rtl] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left {
display: block;
}
.pdf-actions_insert-file-button-container:hover {
opacity: 1;
transition: opacity 0.05s;
}
.pdf-actions_insert-file-button {
position: absolute;
top: 50%;
right: 50%;
translate: 50% -50%;
aspect-ratio: 1;
border-radius: 100px;
}

View file

@ -2,37 +2,65 @@
class DragDropManager { class DragDropManager {
dragContainer; dragContainer;
wrapper;
pageDirection;
movePageTo; movePageTo;
pageDragging; pageDragging;
draggelEl; draggelEl;
draggedImageEl; draggedImageEl;
hoveredEl; hoveredEl;
endInsertionElement;
constructor(id) { constructor(id, wrapperId) {
this.dragContainer = document.getElementById(id); this.dragContainer = document.getElementById(id);
this.pageDirection = document.documentElement.getAttribute("lang-direction");
this.wrapper = document.getElementById(wrapperId);
this.pageDragging = false; this.pageDragging = false;
this.hoveredEl = undefined; this.hoveredEl = undefined;
this.draggelEl = undefined this.draggelEl = undefined
this.draggedImageEl = undefined; this.draggedImageEl = undefined;
var styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = 'css/dragdrop.css'
document.head.appendChild(styleElement);
const div = document.createElement('div');
div.classList.add('drag-manager_endpoint');
div.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-arrow-down" viewBox="0 0 16 16">
<path d="M8.5 6.5a.5.5 0 0 0-1 0v3.793L6.354 9.146a.5.5 0 1 0-.708.708l2 2a.5.5 0 0 0 .708 0l2-2a.5.5 0 0 0-.708-.708L8.5 10.293V6.5z"/>
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
</svg>`
this.endInsertionElement = div;
this.startDraggingPage = this.startDraggingPage.bind(this); this.startDraggingPage = this.startDraggingPage.bind(this);
this.onDragEl = this.onDragEl.bind(this); this.onDragEl = this.onDragEl.bind(this);
this.stopDraggingPage = this.stopDraggingPage.bind(this); this.stopDraggingPage = this.stopDraggingPage.bind(this);
this.adapt(div);
} }
startDraggingPage(div, imageSrc) { startDraggingPage(div,) {
this.pageDragging = true; this.pageDragging = true;
this.draggedEl = div; this.draggedEl = div;
div.classList.add('dragging'); const img = div.querySelector('img');
div.classList.add('drag-manager_dragging');
const imageSrc = img.src;
const imgEl = document.createElement('img'); const imgEl = document.createElement('img');
imgEl.classList.add('dragged-img'); imgEl.classList.add('dragged-img');
imgEl.src = imageSrc; imgEl.src = imageSrc;
this.draggedImageEl = imgEl; this.draggedImageEl = imgEl;
this.draggedImageEl.style.left = screenX; imgEl.style.left = screenX;
this.draggedImageEl.style.right = screenY; imgEl.style.right = screenY;
imgEl.style.transform = `rotate(${img.style.rotate === '' ? '0deg' : img.style.rotate}) translate(-50%, -50%)`;
this.dragContainer.appendChild(imgEl); this.dragContainer.appendChild(imgEl);
window.addEventListener('mouseup', this.stopDraggingPage) window.addEventListener('mouseup', this.stopDraggingPage)
window.addEventListener('mousemove', this.onDragEl) window.addEventListener('mousemove', this.onDragEl)
this.wrapper.classList.add('drag-manager_dragging-container');
this.wrapper.appendChild(this.endInsertionElement);
} }
onDragEl(mouseEvent) { onDragEl(mouseEvent) {
@ -46,14 +74,23 @@ class DragDropManager {
stopDraggingPage() { stopDraggingPage() {
window.removeEventListener('mousemove', this.onDragEl); window.removeEventListener('mousemove', this.onDragEl);
this.wrapper.classList.remove('drag-manager_dragging-container');
this.wrapper.removeChild(this.endInsertionElement);
window.removeEventListener('mouseup', this.stopDraggingPage) window.removeEventListener('mouseup', this.stopDraggingPage)
this.draggedImageEl = undefined; this.draggedImageEl = undefined;
this.pageDragging = false; this.pageDragging = false;
this.draggedEl.classList.remove('dragging'); this.draggedEl.classList.remove('drag-manager_dragging');
this.hoveredEl.classList.remove('draghover'); this.hoveredEl?.classList.remove('drag-manager_draghover');
this.dragContainer.childNodes.forEach((dragChild) => { this.dragContainer.childNodes.forEach((dragChild) => {
this.dragContainer.removeChild(dragChild); this.dragContainer.removeChild(dragChild);
}) })
if(!this.hoveredEl) {
return;
}
if(this.hoveredEl === this.endInsertionElement) {
this.movePageTo(this.draggedEl);
return;
}
this.movePageTo(this.draggedEl, this.hoveredEl); this.movePageTo(this.draggedEl, this.hoveredEl);
} }
@ -64,19 +101,19 @@ class DragDropManager {
adapt(div) { adapt(div) {
const onDragStart = () => { const onDragStart = () => {
this.startDraggingPage(div, div.querySelector('img').src); this.startDraggingPage(div);
} }
const onMouseEnter = () => { const onMouseEnter = () => {
if (this.pageDragging) { if (this.pageDragging) {
this.hoveredEl = div; this.hoveredEl = div;
div.classList.add('draghover'); div.classList.add('drag-manager_draghover');
} }
} }
const onMouseLeave = () => { const onMouseLeave = () => {
this.hoveredEl = undefined this.hoveredEl = undefined
div.classList.remove('draghover'); div.classList.remove('drag-manager_draghover');
} }
div.addEventListener('dragstart', onDragStart); div.addEventListener('dragstart', onDragStart);

View file

@ -5,6 +5,12 @@ class PdfActionsManager {
constructor(id) { constructor(id) {
this.pagesContainer = document.getElementById(id); this.pagesContainer = document.getElementById(id);
this.pageDirection = document.documentElement.getAttribute("lang-direction"); this.pageDirection = document.documentElement.getAttribute("lang-direction");
var styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = 'css/pdfActions.css'
document.head.appendChild(styleElement);
} }
getPageContainer(element) { getPageContainer(element) {
@ -70,20 +76,21 @@ class PdfActionsManager {
} }
adapt(div) { adapt(div) {
div.classList.add('pdf-actions_container');
const leftDirection = this.pageDirection === 'rtl' ? 'right' : 'left' const leftDirection = this.pageDirection === 'rtl' ? 'right' : 'left'
const rightDirection = this.pageDirection === 'rtl' ? 'left' : 'right' const rightDirection = this.pageDirection === 'rtl' ? 'left' : 'right'
const buttonContainer = document.createElement('div'); const buttonContainer = document.createElement('div');
buttonContainer.classList.add("button-container"); buttonContainer.classList.add("pdf-actions_button-container", "hide-on-drag");
const moveUp = document.createElement('button'); const moveUp = document.createElement('button');
moveUp.classList.add("move-left-button","btn", "btn-secondary"); moveUp.classList.add("pdf-actions_move-left-button","btn", "btn-secondary");
moveUp.innerHTML = `<i class="bi bi-arrow-${leftDirection}-short"></i>`; moveUp.innerHTML = `<i class="bi bi-arrow-${leftDirection}-short"></i>`;
moveUp.onclick = this.moveUpButtonCallback; moveUp.onclick = this.moveUpButtonCallback;
buttonContainer.appendChild(moveUp); buttonContainer.appendChild(moveUp);
const moveDown = document.createElement('button'); const moveDown = document.createElement('button');
moveDown.classList.add("move-right-button","btn", "btn-secondary"); moveDown.classList.add("pdf-actions_move-right-button","btn", "btn-secondary");
moveDown.innerHTML = `<i class="bi bi-arrow-${rightDirection}-short"></i>`; moveDown.innerHTML = `<i class="bi bi-arrow-${rightDirection}-short"></i>`;
moveDown.onclick = this.moveDownButtonCallback; moveDown.onclick = this.moveDownButtonCallback;
buttonContainer.appendChild(moveDown); buttonContainer.appendChild(moveDown);
@ -120,12 +127,12 @@ class PdfActionsManager {
const insertFileButtonContainer = document.createElement('div'); const insertFileButtonContainer = document.createElement('div');
insertFileButtonContainer.classList.add( insertFileButtonContainer.classList.add(
"insert-file-button-container", "pdf-actions_insert-file-button-container",
leftDirection, leftDirection,
`align-center-${leftDirection}`); `align-center-${leftDirection}`);
const insertFileButton = document.createElement('button'); const insertFileButton = document.createElement('button');
insertFileButton.classList.add("btn", "btn-primary", "insert-file-button"); insertFileButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16"> insertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
<path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/> <path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/>
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/> <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
@ -138,12 +145,12 @@ class PdfActionsManager {
// add this button to every element, but only show it on the last one :D // add this button to every element, but only show it on the last one :D
const insertFileButtonRightContainer = document.createElement('div'); const insertFileButtonRightContainer = document.createElement('div');
insertFileButtonRightContainer.classList.add( insertFileButtonRightContainer.classList.add(
"insert-file-button-container", "pdf-actions_insert-file-button-container",
rightDirection, rightDirection,
`align-center-${rightDirection}`); `align-center-${rightDirection}`);
const insertFileButtonRight = document.createElement('button'); const insertFileButtonRight = document.createElement('button');
insertFileButtonRight.classList.add("btn", "btn-primary", "insert-file-button"); insertFileButtonRight.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButtonRight.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16"> insertFileButtonRight.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
<path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/> <path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/>
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/> <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>

View file

@ -3,6 +3,13 @@ class ImageHiglighter {
constructor(id) { constructor(id) {
this.imageHighlighter = document.getElementById(id); this.imageHighlighter = document.getElementById(id);
this.imageHighlightCallback = this.imageHighlightCallback.bind(this); this.imageHighlightCallback = this.imageHighlightCallback.bind(this);
var styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = 'css/imageHighlighter.css'
document.head.appendChild(styleElement);
this.imageHighlighter.onclick = () => { this.imageHighlighter.onclick = () => {
this.imageHighlighter.childNodes.forEach((child) => { this.imageHighlighter.childNodes.forEach((child) => {
child.classList.add('remove'); child.classList.add('remove');

View file

@ -67,7 +67,7 @@
import PdfActionsManager from '/js/multitool/PdfActionsManager.js'; import PdfActionsManager from '/js/multitool/PdfActionsManager.js';
// enables drag and drop // enables drag and drop
const dragDropManager = new DragDropManager('drag-container'); const dragDropManager = new DragDropManager('drag-container', 'pages-container');
// enables image highlight on click // enables image highlight on click
const imageHighlighter = new ImageHighlighter('image-highlighter'); const imageHighlighter = new ImageHighlighter('image-highlighter');
// enables the default action buttons on each pdf // enables the default action buttons on each pdf
@ -93,6 +93,7 @@
max-width: 95vw; max-width: 95vw;
margin: 0 auto; margin: 0 auto;
} }
#global-buttons-container { #global-buttons-container {
display: flex; display: flex;
gap: 10px; gap: 10px;
@ -178,27 +179,6 @@
} }
.page-container.dragging {
width: 0px;
visibility: hidden;
}
.page-container.draghover {
width: 500px !important;
}
.page-container.draghover .insert-file-button-container {
display: none !important;
}
.page-container.draghover .button-container {
visibility: hidden !important;
}
.page-container.draghover img {
left: calc(50% + 125px) !important;
}
.page-container img { .page-container img {
/* max-width: calc(100% - 15px); */ /* max-width: calc(100% - 15px); */
max-height: calc(100% - 15px); max-height: calc(100% - 15px);
@ -213,157 +193,6 @@
transition: rotate 0.3s; transition: rotate 0.3s;
} }
.page-container .button-container {
z-index: 2;
display:flex;
opacity: 0;
transition: opacity 0.1s linear;
}
.page-container:hover .button-container {
opacity: 1;
}
.page-container .button-container > * {
padding: 0.25rem 0.5rem;
margin: 3px;
display: block;
}
.page-container svg {
width: 16px;
height: 16px;
}
.page-container:nth-child(1) .move-left-button {
display: none;
}
.page-container:last-child .move-right-button {
display: none;
}
.page-image {
cursor:pointer;
}
/* "insert pdf" buttons that appear on the right when hover */
.insert-file-button-container {
translate: 0 -50%;
width: 80px;
height: 100%;
z-index: 1;
opacity: 0;
transition: opacity 0.2s;
}
.insert-file-button-container.left {
left: -20px;
}
.insert-file-button-container.right {
right: -20px;
}
html[lang-direction=ltr] .insert-file-button-container.right {
display:none;
}
html[lang-direction=rtl] .insert-file-button-container.left {
display:none;
}
.insert-file-button-container.left .insert-file-button {
left: 0;
translate: 0 -50%;
}
.insert-file-button-container.right .insert-file-button {
right: 0;
translate: 0 -50%;
}
html[lang-direction=ltr] .page-container:last-child > .insert-file-button-container.right {
display: block;
}
html[lang-direction=rtl] .page-container:last-child > .insert-file-button-container.left {
display: block;
}
.insert-file-button-container:hover {
opacity: 1;
transition: opacity 0.05s;
}
.insert-file-button {
position: absolute;
top: 50%;
right: 50%;
translate: 50% -50%;
aspect-ratio: 1;
border-radius: 100px;
}
#image-highlighter {
position: fixed;
display:flex;
inset: 0;
z-index: 10000;
background-color: rgba(0, 0, 0, 0);
visibility: hidden;
align-items: center;
justify-content: center;
transition: visbility 0.1s linear, background-color 0.1s linear;
}
#image-highlighter > * {
max-width: 80vw;
max-height: 80vh;
animation: image-highlight .1s linear;
transition: transform .1s linear, opacity .1s linear;
}
#image-highlighter > *.remove {
transform: scale(0.8) !important;
opacity: 0 !important;
}
#image-highlighter:not(:empty) {
background-color: rgba(0, 0, 0, 0.37);
visibility: visible;
}
@keyframes image-highlight {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
#drag-container {
position: fixed;
display:flex;
inset: 0;
pointer-events: none;
z-index: 10000;
visibility: hidden;
}
#drag-container:not(:empty) {
visibility: visible;
}
#drag-container .dragged-img {
position: fixed;
max-width: 200px;
max-height: 200px;
transform: translate(-50%, -50%);
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
}
#add-pdf-button { #add-pdf-button {
margin: 0 auto; margin: 0 auto;
} }