class DragDropManager { constructor(id, wrapperId) { this.dragContainer = document.getElementById(id); this.pageDirection = document.documentElement.getAttribute('dir'); this.wrapper = document.getElementById(wrapperId); this.pageDragging = false; this.hoveredEl = undefined; this.draggedImageEl = undefined; this.draggedEl = undefined; this.selectedPageElements = []; // Store selected pages for multi-page mode this.elementTimeouts = new Map(); // Add CSS dynamically const styleElement = document.createElement('link'); styleElement.rel = 'stylesheet'; styleElement.href = 'css/dragdrop.css'; document.head.appendChild(styleElement); // Create the endpoint element const div = document.createElement('div'); div.classList.add('page-container'); div.classList.add('drag-manager_endpoint'); div.innerHTML = ` `; this.endInsertionElement = div; // Bind methods this.startDraggingPage = this.startDraggingPage.bind(this); this.onDragEl = this.onDragEl.bind(this); this.stopDraggingPage = this.stopDraggingPage.bind(this); this.adapt(div); } startDraggingPage(div) { if (window.selectPage) { // Multi-page drag logic this.selectedPageElements = window.selectedPages .map((index) => { const pageEl = document.getElementById(`page-container-${index}`); if (pageEl) { pageEl.initialTransform = pageEl.style.transform || 'translate(0px, 0px)'; pageEl.classList.add('drag-manager_dragging'); } return pageEl; }) .filter(Boolean); if (this.selectedPageElements.length === 0) return; this.pageDragging = true; this.draggedImageEl = document.createElement('div'); this.draggedImageEl.classList.add('multidrag'); this.draggedImageEl.textContent = `${this.selectedPageElements.length} ${window.translations.dragDropMessage}`; this.draggedImageEl.style.visibility = 'hidden'; this.dragContainer.appendChild(this.draggedImageEl); } else { // Single-page drag logic this.pageDragging = true; this.draggedEl = div; const img = div.querySelector('img'); div.classList.add('drag-manager_dragging'); div.classList.remove('moved-element', 'remove'); const imgEl = document.createElement('img'); imgEl.classList.add('dragged-img'); imgEl.src = img.src; imgEl.style.visibility = 'hidden'; imgEl.style.transform = `rotate(${img.style.rotate === '' ? '0deg' : img.style.rotate}) translate(-50%, -50%)`; this.draggedImageEl = imgEl; this.dragContainer.appendChild(imgEl); } // Common setup for both modes window.addEventListener('mouseup', this.stopDraggingPage); window.addEventListener('mousemove', this.onDragEl); this.wrapper.classList.add('drag-manager_dragging-container'); this.wrapper.appendChild(this.endInsertionElement); } onDragEl(mouseEvent) { const { clientX, clientY } = mouseEvent; if (this.draggedImageEl) { this.draggedImageEl.style.visibility = 'visible'; this.draggedImageEl.style.left = `${clientX}px`; this.draggedImageEl.style.top = `${clientY}px`; } } stopDraggingPage() { window.removeEventListener('mousemove', this.onDragEl); this.wrapper.classList.remove('drag-manager_dragging-container'); this.wrapper.removeChild(this.endInsertionElement); window.removeEventListener('mouseup', this.stopDraggingPage); if (this.draggedImageEl) { this.dragContainer.removeChild(this.draggedImageEl); this.draggedImageEl = undefined; } if (window.selectPage) { // Multi-page drop logic if ( !this.hoveredEl || !this.hoveredEl.classList.contains('page-container') || this.selectedPageElements.includes(this.hoveredEl) ) { this.selectedPageElements.forEach((pageEl) => { pageEl.style.transform = pageEl.initialTransform || 'translate(0px, 0px)'; pageEl.classList.remove('drag-manager_dragging'); }); } else { this.selectedPageElements.forEach((pageEl) => { pageEl.classList.remove('drag-manager_dragging'); if (this.hoveredEl === this.endInsertionElement) { this.movePageTo(pageEl); } else { this.movePageTo(pageEl, this.hoveredEl); } // Handle timeout for the current element this.handleTimeoutForElement(pageEl); }); } this.selectedPageElements = []; window.resetPages(); } else { // Single-page drop logic if ( !this.hoveredEl || !this.hoveredEl.classList.contains('page-container') || this.hoveredEl === this.draggedEl ) { this.draggedEl.style.transform = this.draggedEl.initialTransform || 'translate(0px, 0px)'; this.draggedEl.classList.remove('drag-manager_dragging'); return; } this.draggedEl.classList.remove('drag-manager_dragging'); if (this.hoveredEl === this.endInsertionElement) { this.movePageTo(this.draggedEl); } else { this.movePageTo(this.draggedEl, this.hoveredEl); } // Handle timeout for the current element this.handleTimeoutForElement(this.draggedEl); } this.pageDragging = false; } // Helper function to manage independent timeouts handleTimeoutForElement(element) { // Clear existing timeout if present if (this.elementTimeouts.has(element)) { clearTimeout(this.elementTimeouts.get(element)); } // Add the moved-element class and set a new timeout element.classList.remove('remove'); element.classList.add('moved-element'); const timeoutId = setTimeout(() => { element.classList.add('remove'); this.elementTimeouts.delete(element); // Cleanup the timeout map }, 2000); // Store the timeout ID for this element this.elementTimeouts.set(element, timeoutId); } setActions({ movePageTo }) { this.movePageTo = movePageTo; } adapt(div) { const onDragStart = (e) => { e.preventDefault(); this.startDraggingPage(div); }; const onMouseEnter = () => { if (this.pageDragging) { this.hoveredEl = div; div.classList.add('drag-manager_draghover'); } }; const onMouseLeave = () => { this.hoveredEl = undefined; div.classList.remove('drag-manager_draghover'); }; div.addEventListener('dragstart', onDragStart); div.addEventListener('mouseenter', onMouseEnter); div.addEventListener('mouseleave', onMouseLeave); return div; } } export default DragDropManager;