//Start up code //if (window.location.protocol == "file:") { // let locip = prompt("File Mode. Please enter WLED IP!"); // gId('curlUrl').value = locip; //} else // //Start up code let devMode = false; //Remove gurl.value = location.host; const urlParams = new URLSearchParams(window.location.search); if (gurl.value.length < 1){ gurl.value = "Missing_Host"; } function gen(){ //Generate image if enough info is in place //Is host non empty //Is image loaded //is scale > 0 if (((szX.value > 0 && szY.value > 0) || szDiv.style.display == 'none') && gurl.value.length > 0 && prw.style.display != 'none'){ //regenerate let base64Image = prw.src; if (isValidBase64Gif(base64Image)) { im.src = base64Image; getPixelRGBValues(base64Image); imcn.style.display = "block"; bcn.style.display = ""; } else { let imageInfo = '

WARNING! File does not appear to be a valid image

'; imin.innerHTML = imageInfo; imin.style.display = "block"; imcn.style.display = "none"; JLD.value = ''; if (devMode) console.log("The string '" + base64Image + "' is not a valid base64 image."); } } if(gurl.value.length > 0){ gId("sSg").setAttribute("fill", accentColor); } else{ gId("sSg").setAttribute("fill", accentTextColor); let ts = tSg; ts.style.display = "none"; ts.innerHTML = ""; sID.style.display = "flex"; } } // Code for copying the generated string to clipboard cjb.addEventListener('click', async () => { let JSONled = JLD; JSONled.select(); try { await navigator.clipboard.writeText(JSONled.value); } catch (err) { try { await d.execCommand("copy"); } catch (err) { console.error('Failed to copy text: ', err); } } }); // Event listeners ======================= lSS.addEventListener("change", gen); szY.addEventListener("change", gen); szX.addEventListener("change", gen); cFS.addEventListener("change", gen); aS.addEventListener("change", gen); brgh.addEventListener("change", gen); cLN.addEventListener("change", gen); haIDe.addEventListener("change", gen); haUe.addEventListener("change", gen); haNe.addEventListener("change", gen); gurl.addEventListener("change", gen); sID.addEventListener("change", gen); prw.addEventListener("load", gen); //gId("convertbutton").addEventListener("click", gen); tSg.addEventListener("change", () => { sop = tSg.options[tSg.selectedIndex]; szX.value = sop.dataset.x; szY.value = sop.dataset.y; gen(); }); gId("sendJSONledbutton").addEventListener('click', async () => { if (window.location.protocol === "https:") { alert('Will only be available when served over http (or WLED is run over https)'); } else { postPixels(); } }); brgh.oninput = () => { brgV.textContent = brgh.value; let perc = parseInt(brgh.value)*100/255; var val = `linear-gradient(90deg, #bbb ${perc}%, #333 ${perc}%)`; brgh.style.backgroundImage = val; } cLN.oninput = () => { let cln = cLN; cLV.textContent = cln.value; let perc = parseInt(cln.value)*100/512; var val = `linear-gradient(90deg, #bbb ${perc}%, #333 ${perc}%)`; cln.style.backgroundImage = val; } frm.addEventListener("change", () => { for (var i = 0; i < hideableRows.length; i++) { hideableRows[i].classList.toggle("hide", frm.value !== "ha"); gen(); } }); async function postPixels() { let ss = gId("sendSvgP"); ss.setAttribute("fill", prsCol); let er = false; for (let i of httpArray) { try { if (devMode) console.log(i); if (devMode) console.log(i.length); const response = await fetch('http://'+gId('curlUrl').value+'/json/state', { method: 'POST', headers: { 'Content-Type': 'application/json' //'Content-Type': 'text/html; charset=UTF-8' }, body: i }); const data = await response.json(); if (devMode) console.log(data); } catch (error) { console.error(error); er = true; } } if(er){ //Something went wrong ss.setAttribute("fill", redColor); setTimeout(function(){ ss.setAttribute("fill", accentTextColor); }, 1000); } else { // A, OK ss.setAttribute("fill", greenColor); setTimeout(function(){ ss.setAttribute("fill", accentColor); }, 1000); } } //File uploader code const dropZone = gId('drop-zone'); const filePicker = gId('file-picker'); const preview = prw; // Listen for dragenter, dragover, and drop events dropZone.addEventListener('dragenter', dragEnter); dropZone.addEventListener('dragover', dragOver); dropZone.addEventListener('drop', dropped); dropZone.addEventListener('click', zoneClicked); // Listen for change event on file picker filePicker.addEventListener('change', filePicked); // Handle zone click function zoneClicked(e) { e.preventDefault(); //this.classList.add('drag-over'); //alert('Hej'); filePicker.click(); } // Handle dragenter function dragEnter(e) { e.preventDefault(); this.classList.add('drag-over'); } // Handle dragover function dragOver(e) { e.preventDefault(); } // Handle drop function dropped(e) { e.preventDefault(); this.classList.remove('drag-over'); // Get the dropped file const file = e.dataTransfer.files[0]; updatePreview(file) } // Handle file picked function filePicked(e) { // Get the picked file const file = e.target.files[0]; updatePreview(file) } // Update the preview image function updatePreview(file) { // Use FileReader to read the file const reader = new FileReader(); reader.onload = () => { // Update the preview image preview.src = reader.result; //gId("submitConvertDiv").style.display = ""; prw.style.display = ""; }; reader.readAsDataURL(file); } function isValidBase64Gif(string) { // Use a regular expression to check that the string is a valid base64 string /* const base64gifPattern = /^data:image\/gif;base64,([A-Za-z0-9+/:]{4})*([A-Za-z0-9+/:]{3}=|[A-Za-z0-9+/:]{2}==)?$/; const base64pngPattern = /^data:image\/png;base64,([A-Za-z0-9+/:]{4})*([A-Za-z0-9+/:]{3}=|[A-Za-z0-9+/:]{2}==)?$/; const base64jpgPattern = /^data:image\/jpg;base64,([A-Za-z0-9+/:]{4})*([A-Za-z0-9+/:]{3}=|[A-Za-z0-9+/:]{2}==)?$/; const base64webpPattern = /^data:image\/webp;base64,([A-Za-z0-9+/:]{4})*([A-Za-z0-9+/:]{3}=|[A-Za-z0-9+/:]{2}==)?$/; */ //REMOVED, Any image appear to work as long as it can be drawn to the canvas. Leaving code in for future use, possibly if (1==1 || base64gifPattern.test(string) || base64pngPattern.test(string) || base64jpgPattern.test(string) || base64webpPattern.test(string)) { return true; } else { //Not OK return false; } } var hideableRows = d.querySelectorAll(".ha-hide"); for (var i = 0; i < hideableRows.length; i++) { hideableRows[i].classList.add("hide"); } frm.addEventListener("change", () => { for (var i = 0; i < hideableRows.length; i++) { hideableRows[i].classList.toggle("hide", frm.value !== "ha"); } }); function switchScale() { //let scalePath = gId("scaleDiv").children[1].children[0] let scaleTogglePath = scDiv.children[0].children[0] let color = scaleTogglePath.getAttribute("fill"); let d = ''; if (color === accentColor) { color = accentTextColor; d = scaleToggleOffd; szDiv.style.display = "none"; // Set values to actual XY of image, if possible } else { color = accentColor; d = scaleToggleOnd; szDiv.style.display = ""; } //scalePath.setAttribute("fill", color); scaleTogglePath.setAttribute("fill", color); scaleTogglePath.setAttribute("d", d); gen(); } function generateSegmentOptions(array) { //This function is prepared for a name property on each segment for easier selection //Currently the name is generated generically based on index tSg.innerHTML = ""; for (var i = 0; i < array.length; i++) { var option = cE("option"); option.value = array[i].value; option.text = array[i].text; option.dataset.x = array[i].x; option.dataset.y = array[i].y; tSg.appendChild(option); if(i === 0) { option.selected = true; szX.value = option.dataset.x; szY.value = option.dataset.y; } } } // Get segments from device async function getSegments() { cv = gurl.value; if (cv.length > 0 ){ try { var arr = []; const response = await fetch('http://'+cv+'/json/state'); const json = await response.json(); let ids = json.seg.map(sg => ({id: sg.id, n: sg.n, xs: sg.start, xe: sg.stop, ys: sg.startY, ye: sg.stopY})); for (var i = 0; i < ids.length; i++) { arr.push({ value: ids[i]["id"], text: ids[i]["n"] + ' (index: ' + ids[i]["id"] + ')', x: ids[i]["xe"] - ids[i]["xs"], y: ids[i]["ye"] - ids[i]["ys"] }); } generateSegmentOptions(arr); tSg.style.display = "flex"; sID.style.display = "none"; gId("sSg").setAttribute("fill", greenColor); setTimeout(function(){ gId("sSg").setAttribute("fill", accentColor); }, 1000); } catch (error) { console.error(error); gId("sSg").setAttribute("fill", redColor); setTimeout(function(){ gId("sSg").setAttribute("fill", accentColor); }, 1000); tSg.style.display = "none"; sID.style.display = "flex"; } } else{ gId("sSg").setAttribute("fill", redColor); setTimeout(function(){ gId("sSg").setAttribute("fill", accentTextColor); }, 1000); tSg.style.display = "none"; sID.style.display = "flex"; } } //Initial population of segment selection function generateSegmentArray(noOfSegments) { var arr = []; for (var i = 0; i < noOfSegments; i++) { arr.push({ value: i, text: "Segment index " + i }); } return arr; } var segmentData = generateSegmentArray(10); generateSegmentOptions(segmentData); seDiv.innerHTML = '' /*gId("convertbutton").innerHTML = '   Convert to WLED JSON '; */ cjb.innerHTML = '   Copy to clipboard'; gId("sendJSONledbutton").innerHTML = '   Send to device'; //After everything is loaded, check if we have a possible IP/host if(gurl.value.length > 0){ // Needs to be addressed directly here so the object actually exists gId("sSg").setAttribute("fill", accentColor); }