Peter-Young's picture
Upload folder using huggingface_hub
5193146 verified
import { $el } from "/scripts/ui.js";
import { imageDrawerComponentManagerInstance } from "../ImageDrawer/Core/ImageDrawerModule.js";
export class ModalManager {
constructor(imageIndex = undefined) {
// If this modal is representing an image in imageList,
// add functionality to switch to neighboring images or
// enable auto mode / slideshows
this._imageIndex = imageIndex;
// Zoom and Pan functionality
this._scale = 1;
this._translateX = -50; // Initial translate X percentage
this._translateY = -50; // Initial translate Y percentage
this._bIsPanningActive = false;
this._bHasPanned = false;
this._startX = 0;
this._startY = 0;
this._modalContainer;
this._modalContent;
this.handleKeyDownFunction;
this._bButtonPressed = false;
}
createModal(modalContent,) {
if (!modalContent) { return; }
this._modalContent = modalContent;
this._setModalContentStyle();
// Append modal content to modal container
this._getOrCreateModalContainer().appendChild(this._modalContent);
this._createModalControlButtons();
this.handleKeyDownFunction = (event) => { this._handleKeyDown(event); };
// Add key event listeners
document.addEventListener("keydown", this.handleKeyDownFunction);
return this._getOrCreateModalContainer();
}
createModalReadyImage(href) {
return $el("img", {
src: href,
style: {
position: 'relative',
width: '99vw',
height: '99vh',
objectFit: 'contain',
display: 'block',
margin: 'auto',
},
});
}
_setModalContentStyle() {
this._modalContent.style.position = 'absolute';
this._modalContent.style.display = "inline-block";
this._modalContent.style.left = "50%";
this._modalContent.style.top = "50%";
this._modalContent.style.transform = "translate(-50%, -50%)";
this._modalContent.style.maxWidth = "99%";
this._modalContent.style.maxHeight = "99%";
this._modalContent.style.overflow = "hidden";
// Prevent drag & drop operation
this._modalContent.draggable = false;
}
_createAndOpenModalContainer() {
this._modalContainer = document.createElement("div");
this._modalContainer.style.display = "block";
this._modalContainer.style.position = "fixed";
this._modalContainer.style.zIndex = "10000";
this._modalContainer.style.left = "0";
this._modalContainer.style.top = "0";
this._modalContainer.style.width = "100%";
this._modalContainer.style.height = "100%";
this._modalContainer.style.overflow = "auto";
this._modalContainer.style.backgroundColor = "rgba(0,0,0,0.7)";
this._modalContainer.addEventListener("wheel", (event) => { event.preventDefault(); this._zoom(event); });
this._modalContainer.addEventListener("mousedown", (event) => { event.preventDefault(); this._startPan(event); });
this._modalContainer.addEventListener("mousemove", (event) => { event.preventDefault(); this._pan(event); });
this._modalContainer.addEventListener("mouseup", (event) => { event.preventDefault(); this._onMouseUp(event); });
this._modalContainer.addEventListener("mouseleave", (event) => { event.preventDefault(); this._endPan(); });
// Prevent drag & drop operation
this._modalContainer.addEventListener("dragstart", (event) => { event.preventDefault(); });
this._modalContainer.draggable = false;
this._modalContainer.data = this;
// Append modal container to the document body
document.body.appendChild(this._modalContainer);
}
_getOrCreateModalContainer() {
if (!this._modalContainer) {
this._createAndOpenModalContainer();
}
return this._modalContainer;
}
_createModalControlButtons() {
const createButton = (text, tooltip, clickFunction) => {
const button = $el("button", {
title: tooltip,
textContent: text,
style: {
background: "none",
border: "none",
padding: "0px",
color: "white",
fontWeight: "bolder",
fontSize: "400%",
cursor: 'pointer',
position: "absolute",
filter: "drop-shadow(13px 0px black)",
},
onmousedown: () => {
this._bButtonPressed = true;
},
onclick: clickFunction,
});
button.classList.add("JNodes-interactive-container");
return button;
}
const previousImageButton = createButton("<", "See previous image", () => { this._displayNeighbouringImage(-1); });
previousImageButton.style.left = "2.5%";
previousImageButton.style.top = "50%";
this._getOrCreateModalContainer().appendChild(previousImageButton);
const nextImageButton = createButton(">", "See next image", () => { this._displayNeighbouringImage(1); });
nextImageButton.style.right = "2.5%";
nextImageButton.style.top = "50%";
this._getOrCreateModalContainer().appendChild(nextImageButton);
// Count
if (this._imageIndex != undefined) {
const imageDrawerListInstance = imageDrawerComponentManagerInstance.getComponentByName("ImageDrawerList");
const currentListChildren = imageDrawerListInstance.getVisibleImageListChildren();
const countWidget = $el("label", {
textContent: `${this._imageIndex + 1}/${currentListChildren.length}`,
style: {
background: "rgba(0,0,0,0.5)",
color: "white",
fontWeight: "bolder",
fontSize: "100%",
fontFamily: "arial",
position: "absolute",
right: "1%",
top: "1%"
}
});
this._getOrCreateModalContainer().appendChild(countWidget);
}
}
// Function to close the modal and destroy the class instance
_closeModal() {
if (this._modalContainer && this._modalContainer.parentNode) {
this._modalContainer.parentNode.removeChild(this._modalContainer);
}
document.removeEventListener("keydown", this.handleKeyDownFunction);
delete this;
}
_handleKeyDown(event) {
if (event.key === "Escape") {
event.preventDefault();
this._closeModal();
} else if (event.key === "ArrowLeft") {
event.preventDefault();
this._displayNeighbouringImage(-1);
} else if (event.key === "ArrowRight") {
event.preventDefault();
this._displayNeighbouringImage(1);
}
}
_zoom(event) {
event.preventDefault(); // Prevent the default scroll behavior
const zoomSpeed = 0.1;
const delta = event.deltaY;
// Adjust the scale based on scroll direction
if (delta > 0) {
this._scale = Math.max(0.1, this._scale - zoomSpeed); // Zoom out
} else {
this._scale = Math.min(5, this._scale + zoomSpeed); // Zoom in
}
// Apply the scale and initial translate to the modal content
this._modalContent.style.transform = `translate(${this._translateX}%, ${this._translateY}%) scale(${this._scale})`;
}
_startPan(event) {
this._bIsPanningActive = true;
this._getOrCreateModalContainer().style.cursor = "grabbing";
this._startX = event.clientX;
this._startY = event.clientY;
}
_pan(event) {
if (!this._bIsPanningActive) return;
const dx = event.clientX - this._startX;
const dy = event.clientY - this._startY;
// Adjust translate values
this._translateX += (dx / this._getOrCreateModalContainer().clientWidth) * 100;
this._translateY += (dy / this._getOrCreateModalContainer().clientHeight) * 100;
// Update start positions for next movement
this._startX = event.clientX;
this._startY = event.clientY;
// Apply the transformation
this._modalContent.style.transform = `translate(${this._translateX}%, ${this._translateY}%) scale(${this._scale})`;
this._bHasPanned = true;
}
_endPan() {
this._bIsPanningActive = false;
this._getOrCreateModalContainer().style.cursor = "grab";
}
_onMouseUp(event) {
this._endPan();
if (this._bButtonPressed == true) {
this._bButtonPressed = false;
return;
}
if (this._bHasPanned) {
this._bHasPanned = false;
} else if (event.button == 0) { // Left mouse button only can close
this._closeModal();
}
}
_displayNeighbouringImage(offset = 0) {
if (this._imageIndex !== undefined) {
const imageDrawerListInstance = imageDrawerComponentManagerInstance.getComponentByName("ImageDrawerList");
const currentListChildren = imageDrawerListInstance.getVisibleImageListChildren();
let newImageIndex = this._imageIndex;
let newImage;
// Loop until we find an image format child
do {
newImageIndex += offset;
// Wrap index to first or last index at the extremes
newImageIndex = ((newImageIndex % currentListChildren.length) + currentListChildren.length) % currentListChildren.length;
newImage = currentListChildren[newImageIndex];
// Break if we round back to the original image index
if (newImageIndex == this._imageIndex) {
break;
}
} while (newImage?.bIsVideoFormat);
const modalManager = new ModalManager(newImageIndex);
modalManager.createModal(modalManager.createModalReadyImage(newImage.fileInfo.href));
this._closeModal();
}
}
}