const target = document.getElementById("comments"); target.style.backgroundColor = "rgba(192,192,255,0.75)"; target.style.padding = "0.5em"; target.style.borderRadius = "0.5em"; const header = document.createElement("p"); header.innerHTML = "Comments - click to display area of interest
"; const body = document.createElement("div"); commentList = document.createElement("ul"); commentList.id = "commentlist"; body.appendChild(commentList); const nick = document.createElement("input"); nick.id = "comment-nick"; nick.title = "Username for comment"; const nickLabel = document.createElement("label"); nickLabel.htmlFor = "comment-nick"; const input = document.createElement("input"); input.title = "Comment text"; input.size = "100"; const submit = document.createElement("button"); submit.textContent = "submit"; submit.title = "Submit comment"; const info = document.createElement("p"); info.innerHTML = "Tap coordinates on the final image or timelapse to set area and time of interest. Submitting a comment will make your username/chosen nickname public. Do not abuse."; const footer = document.createElement("p"); footer.style.fontFamily = "monospace"; footer.textContent = ""; target.appendChild(header); const hideComments = document.getElementById("hidecomments"); hideComments.onclick = function () { body.style.display = body.style.display === "none" ? "block" : "none"; hideComments.textContent = body.style.display === "none" ? "show comments" : "hide comments"; } target.appendChild(body); body.appendChild(nick); body.appendChild(nickLabel); body.appendChild(input); body.appendChild(submit); body.appendChild(info); body.appendChild(footer); let x = NaN, y = NaN, w = NaN, h = NaN, tStart = NaN, tEnd = NaN; let tLast, backupCanvas; submit.onclick = function () { const text = input.value; input.value = ""; const data = { text:text, canvas: commentsCanvas, x: x, y: y, w: w, h: h, tStart: tStart, tEnd: tEnd } if (auth.authed) { data.user = auth.user; data.hash = auth.hash; } else { data.user = nick.value === "" ? "anonymous" : nick.value; data.hash = -1; } fetch(`/pxlsarchive/comment.php`, { method: "post", body: JSON.stringify(data), headers: { "content-type": "application/json" } } ).then( function(result) { while (commentList.firstChild) { commentList.removeChild(commentList.firstChild); } populateComments(); } ); } document.addEventListener("_pxlsFiddle-auth",function () { if (auth.authed) { nick.value = auth.user; nick.disabled = true; } }); const finalImage = document.getElementById("final"); const finalOverlay = document.getElementById("finaloverlay"); document.addEventListener("_panZoomEvent",timelapseClick); function showArea(xPos,yPos,width,height,tStart,tEnd) { if (typeof x === "undefined") { // entire canvas } else { finalOverlay.width = finalImage.naturalWidth; finalOverlay.height = finalImage.naturalHeight; const ctx = finalOverlay.getContext("2d"); ctx.strokeStyle = "rgba(255,128,0,1)"; ctx.lineWidth = 8; ctx.fillStyle = "rgba(255,128,0,0.1)"; if (isNaN(width)) { // just a spot ctx.beginPath(); ctx.arc(xPos+0.5,yPos+0.5,31,0,2*Math.PI) ctx.stroke(); ctx.fill(); } else { // region ctx.fillRect(xPos+0.5,yPos+0.5,width,height); ctx.rect(xPos+0.5,yPos+0.5,width,height); ctx.stroke(); ctx.fill(); } if (!isNaN(tStart)) { const sources = btnTimelapse.dataset.sources.split(","); const crop = { x: xPos - 16, y: yPos - 16, w: width + 16 + 16, h: height + 16 + 16 }; startTime = tStart; endTime = isNaN(tEnd) ? NaN : tEnd; panZoom.video(sources,{ crop: crop, highlightCrop: true, startTime: startTime - 1, endTime: endTime + 1, chapters:[tStart,tEnd], timeMultiplier:30*300 // 30fps * 300s/frame }); }; } } function clearArea() { const ctx = finalOverlay.getContext("2d"); ctx.clearRect(0, 0, finalOverlay.width, finalOverlay.height); } function commentClick(canvas,xPos,yPos,t) { const ctx = canvas.getContext("2d"); ctx.strokeStyle = "rgba(255,128,0,1)"; ctx.lineWidth = 4; ctx.fillStyle = "rgba(255,128,0,0.1)"; if (isNaN(x)) { tLast = t; backupCanvas = document.createElement("canvas"); backupCanvas.width = canvas.width; backupCanvas.height = canvas.height; backupCanvasCtx = backupCanvas.getContext("2d"); backupCanvasCtx.drawImage(canvas,0,0); x = parseInt(xPos,10); y = parseInt(yPos,10); ctx.beginPath(); ctx.arc(x+0.5,y+0.5,31,0,2*Math.PI) ctx.stroke(); ctx.fill(); tStart = t; } else { if (t === tLast) { ctx.drawImage(backupCanvas,0,0); } if (isNaN(w)) { if (xPos < x) { w = parseInt(x - xPos); x = xPos } else { w = parseInt(xPos - x); } if (yPos < y) { h = parseInt(y - yPos); y = yPos } else { h = parseInt(yPos - y); } ctx.beginPath(); ctx.fillRect(x+0.5,y+0.5,w,h); ctx.rect(x+0.5,y+0.5,w,h); ctx.stroke(); ctx.fill(); if (t !== tStart) { if (t < tStart) { tEnd = tStart; tStart = t; } else { tEnd = t; } } } else { if (t === tLast) { ctx.drawImage(backupCanvas,0,0); } ctx.drawImage(backupCanvas,0,0); x = NaN; y = NaN; w = NaN; h = NaN; tStart = NaN; tEnd = NaN; } } if (isNaN(x)) { footer.textContent = "No coordinates set - presuming comment is for entire canvas"; } else { if (isNaN(w)) { footer.textContent = `Coordinate of interest set... x=${x} y=${y}`; } else { footer.textContent = `Rect of interest set... x=${x} y=${y} w=${w} h=${h}`; } } if (!isNaN(tStart)) { if (!isNaN(tEnd)) { footer.textContent += ` from time index ${tStart} to time index ${tEnd}`; } else { footer.textContent += ` at time index ${tStart}`; } } } function timelapseClick() { commentClick(panZoomEvent.canvas,panZoomEvent.x,panZoomEvent.y,panZoomEvent.t); } finalOverlay.style.pointerEvents = "none"; finalImage.onclick = function (e) { finalOverlay.width = finalImage.naturalWidth; finalOverlay.height = finalImage.naturalHeight; const pos = imgZoom.getImgMousePos(finalImage,e); commentClick(finalOverlay,pos.x,pos.y,NaN); }; function populateComments() { fetch(`/pxlsarchive/comment?canvas=${commentsCanvas}`).then( function (response) { if (response.status !== 200) { // infobar.show(`Could not fetch ${board.config.domain} board info - status: ${response.status}`,"#fff","#800"); return; } response.json().then(function(comments) { const list = commentList; list.onclick = function (e) { const data = e.target.dataset; showArea(parseInt(data.x,10),parseInt(data.y,10),parseInt(data.w,10),parseInt(data.h,10),parseFloat(data.tStart),parseFloat(data.tEnd)); } list.onmouseover = function (e) { const data = e.target.dataset; showArea(parseInt(data.x,10),parseInt(data.y,10),parseInt(data.w,10),parseInt(data.h,10)); } list.onmouseout = function (e) { clearArea(finalOverlay); } for (let i = 0; i < comments.length; i += 1) { const comment = comments[i]; const commentElement = document.createElement("li"); if (comment.x) { commentElement.dataset.x = comment.x; commentElement.dataset.y = comment.y; if (comment.w) { commentElement.dataset.w = comment.w; commentElement.dataset.h = comment.h; } if (comment.tStart) { commentElement.dataset.tStart = comment.tStart; // btnTimelapse.dataset.chapters = "1,2,3,4,5"; if (comment.tEnd) { commentElement.dataset.tEnd = comment.tEnd; } } } commentElement.innerHTML = `${comment.authed ? "" : ""}${comment.user}${comment.authed ? "" : ""}: ${comment.tStart ? "🎞️" : (comment.w ? "◼️" : (comment.x ? "⚫" : ""))} ${comment.comment}`; if (!comment.hidden) { list.appendChild(commentElement); } } return; }); } ).catch(function(err) { // infobar.show(`Could not fetch ${board.config.domain} board info - error: ${err}`,"#fff","#800"); return; }); } populateComments();