// Get the container to use as a canvas const container = document.getElementById("container"); const editor = document.getElementById("editor"); const textForm = document.getElementsByClassName("text-input")[0]; const input = document.getElementById("input"); const insert = document.getElementById("insert"); const cancel = document.getElementById("cancel"); // List of labels let labels = []; let closing = false; // Start is where the mouse is pressed, End is where the mouse is released let startX; let startY; let endX; let endY; // Minimum size for the label to be created let minimumSizeX = 25; let minimumSizeY = 25; // Boolean for showing the editor during drawing let showEditor = false; // Store the coordinates and trigger the function container.addEventListener("mousedown", (e) => { // Avoid inserting a new label if the user is clicking on a close button) if (e.target.tagName !== "BUTTON" && e.target.tagName !== "INPUT") { startX = e.x; startY = e.y; // activate the editor showEditor = true; editor.classList.add("show-editor"); } }); container.addEventListener("mouseup", (e) => { if (e.target.tagName !== "BUTTON" && e.target.tagName !== "INPUT") { endX = e.x; endY = e.y; // disable the editor showEditor = false; editor.classList.remove("show-editor"); editor.style.width = 0; editor.style.height = 0; // draw label drawLabel(); } }); // Edit the editor box using transform instead of left / top in order to be more efficient // (but still with width and height ehm idk if this affects the performance a lot) // (and it is something we must care of because this event is called like every frame that the mouse is dragged) container.addEventListener("mousemove", (e) => { if (showEditor) { let minX = Math.min(startX, e.x); let minY = Math.min(startY, e.y); let maxX = Math.max(startX, e.x); let maxY = Math.max(startY, e.y); let width = maxX - minX; let height = maxY - minY; // Apply a different class when the sizes pass the minimum size // (i don't know if is good made like this) if (width > minimumSizeX && height > minimumSizeY) { editor.classList.add("can-draw"); } else { editor.classList.remove("can-draw"); } editor.style.transform = `translate(${minX}px, ${minY}px)`; editor.style.width = `${maxX - minX}px`; editor.style.height = `${maxY - minY}px`; } }); // Check the mouse direction and create the Label // The origin points of the label (because is positioned with top left) are always the lowest x and y values // The width and height are the greater x and y values (because width and height cannot be negative) function drawLabel() { let minX = Math.min(startX, endX); let minY = Math.min(startY, endY); let maxX = Math.max(startX, endX); let maxY = Math.max(startY, endY); let width = maxX - minX; let height = maxY - minY; if (width > minimumSizeX && height > minimumSizeY) { // Create a label and push it into the array of labels let temporaryLabel = createLabel(minX, minY, width, height, labels.length); temporaryLabel.classList.add("temporary"); temporaryLabel.id = "temporary-label"; container.appendChild(temporaryLabel); new Promise(function (resolve, reject) { // then if the user click insert and there is a value in the input-- > resolve the promise and return the text input to create the label, // if the user click cancel-- > reject the promise and don't create the label textForm.classList.add("visible"); input.focus(); // Insert button insert.addEventListener("click", (e) => { e.preventDefault(); if (input.value) { resolve(); } }); // Cancel button cancel.addEventListener("click", (e) => { e.preventDefault(); textForm.classList.remove("visible"); reject("no input"); }); }).then(() => { // Create the label let label = createLabel(minX, minY, width, height, labels.length); // Add the text input to the label let text = document.createElement("p"); text.classList.add("label--text"); text.innerHTML = input.value; label.appendChild(text); labels.push(label); container.appendChild(label); createLabelTranscription(label); // Reset the modal input.value = ""; input.blur(); let tempLabel = document.getElementById("temporary-label"); container.removeChild(tempLabel); textForm.classList.remove("visible"); }); } } // Create the label element function createLabel(x, y, width, height, index) { let label = document.createElement("div"); label.classList.add("label"); label.style.left = `${x}px`; label.style.top = `${y}px`; label.style.width = `${width}px`; label.style.height = `${height}px`; // data attribute index maybe we will need it later maybe not // with the index number of the label label.setAttribute("data-index", index); // Insert the number in the label let labelNumber = document.createElement("p"); labelNumber.classList.add("label--number"); labelNumber.innerHTML = index + 1; label.appendChild(labelNumber); // Add a button for deleting the label // TODO: reactive numbering oh no let close = document.createElement("button"); close.classList.add("label--close"); close.innerHTML = "x"; close.addEventListener("click", (e) => { label.remove(); }); label.appendChild(close); return label; } const transcriptionPanel = document.getElementById("transcription-panel"); const transcriptionList = transcriptionPanel.querySelector("ol"); function createLabelTranscription(label) { let transcription = document.createElement("li"); transcription.innerHTML = label.querySelector(".label--text").innerHTML; transcriptionList.appendChild(transcription); }