Files
PixelArtConverter/pixart.htm
Henrik c17270360b Version 1.0.8
Changed name of main html file to align with WLED naming.
Fixed HEX (quotation)
Fixed recalculate om changed format
Changed example text in selection drop downs for HEX
Added exmpainatory text to JSON when multiple commands are generated.
2023-04-02 15:18:30 +02:00

100 lines
24 KiB
HTML

<!DOCTYPE html> <html> <head> <meta http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate"> <meta http-equiv="Pragma"
content="no-cache"> <meta http-equiv="Expires" content="0"> <title>
WLED Pixel Art Converter</title> <style>
.box{border:2px solid #fff}body{font-family:Arial,sans-serif;background-color:#111}.top-part{width:600px;margin:0 auto}.container{max-width:100% -40px;border-radius:0;padding:20px;text-align:center}h1{font-size:2.3em;color:#ddd;margin:1px 0;font-family:Arial,sans-serif;line-height:.5}h2{font-size:1.1em;color:rgba(221,221,221,.61);margin:1px 0;font-family:Arial,sans-serif;line-height:.5;text-align:center}h3{font-size:.7em;color:rgba(221,221,221,.61);margin:1px 0;font-family:Arial,sans-serif;line-height:1.4;text-align:center;align-items:center;justify-content:center;display:flex}p{font-size:1em;color:#777;line-height:1.5;font-family:Arial,sans-serif}#fieldTable{font-size:1 em;color:#777;line-height:1;font-family:Arial,sans-serif}#scaleTable{font-size:1 em;color:#777;line-height:1;font-family:Arial,sans-serif}#drop-zone{display:block;width:100%-40px;border:3px dashed #ddd;border-radius:0;text-align:center;padding:20px;margin:0;cursor:pointer;font-family:Arial,sans-serif;font-size:15px;color:#777}#file-picker{display:none}.adaptiveTD{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center}.mainSelector{background-color:#222;color:#ddd;border:1px solid #333;margin-top:4px;margin-bottom:4px;padding:0 8px;height:28px;font-size:15px;border-radius:7px;flex-grow:1;display:flex;align-items:center;justify-content:center}.adaptiveSelector{background-color:#222;color:#ddd;border:1px solid #333;margin-top:4px;margin-bottom:4px;padding:0 8px;height:28px;font-size:15px;border-radius:7px;flex-grow:1;display:none}.segmentsDiv{width:36px;padding-left:5px}* input[type=range]{appearance:none;-moz-appearance:none;-webkit-appearance:none;flex-grow:1;padding:0;margin:4px 8px 4px 0;background-color:transparent;cursor:pointer;background:linear-gradient(to right,#bbb 50%,#333 50%);border-radius:7px}input[type=range]:focus{outline:0}input[type=range]::-webkit-slider-runnable-track{height:28px;cursor:pointer;background:0 0;border-radius:7px}input[type=range]::-webkit-slider-thumb{height:16px;width:16px;border-radius:50%;background:#fff;cursor:pointer;-webkit-appearance:none;margin-top:4px;border-radius:7px}input[type=range]::-moz-range-track{height:28px;background-color:rgba(0,0,0,0);border-radius:7px}input[type=range]::-moz-range-thumb{border:0 solid transparent;height:16px;width:16px;border-radius:7px;background:#fff}.rangeNumber{width:20px;vertical-align:middle}.fullTextField[type=text]{background-color:#222;border:1px solid #333;padding-inline-start:5px;margin-top:4px;margin-bottom:4px;height:24px;border-radius:0;font-family:Arial,sans-serif;font-size:15px;color:#ddd;border-radius:7px;flex-grow:1;display:flex;align-items:center;justify-content:center}.flxTFld{background-color:#222;border:1px solid #333;padding-inline-start:5px;height:24px;border-radius:0;font-family:Arial,sans-serif;font-size:15px;color:#ddd;border-radius:7px;flex-grow:1;display:flex;align-items:center;justify-content:center}* input[type=submit]{background-color:#222;border:1px solid #333;padding:.5em;width:100%;border-radius:24px;font-family:Arial,sans-serif;font-size:1.3em;color:#ddd}* button{background-color:#222;border:1px solid #333;padding-inline:5px;width:100%;border-radius:24px;font-family:Arial,sans-serif;font-size:1em;color:#ddd;display:flex;align-items:center;justify-content:center;cursor:pointer}#scaleDiv{display:flex;align-items:center;vertical-align:middle}textarea{grid-row:1/2;width:100%;height:200px;background-color:#222;border:1px solid #333;color:#ddd}.hide{display:none}.svg-icon{vertical-align:middle}#image-container{display:grid;grid-template-rows:1fr 1fr}#button-container{display:flex;padding-bottom:10px;padding-top:10px}.buttonclass{flex:1;padding-top:5px;padding-bottom:5px}.gap{width:10px}#submitConvert::before{content:"";display:inline-block;background-image:url('data:image/svg+xml;utf8, <svg style="width:24px;height:24px" viewBox="0 0 24 24" <path fill="currentColor" d="M12,6V9L16,5L12,1V4A8,8 0 0,0 4,12C4,13.57 4.46,15.03 5.24,16.26L6.7,14.8C6.25,13.97 6,13 6,12A6,6 0 0,1 12,6M18.76,7.74L17.3,9.2C17.74,10.04 18,11 18,12A6,6 0 0,1 12,18V15L8,19L12,23V20A8,8 0 0,0 20,12C20,10.43 19.54,8.97 18.76,7.74Z" /></svg>');width:36px;height:36px}#sizeDiv *{display:inline-block}.sizeInputFields{width:50px;background-color:#222;border:1px solid #333;padding-inline-start:5px;margin-top:-5px;height:24px;border-radius:7px;font-family:Arial,sans-serif;font-size:15px;color:#ddd}a:link{color:rgba(221,221,221,.61);background-color:transparent;text-decoration:none}a:visited{color:rgba(221,221,221,.61);background-color:transparent;text-decoration:none}a:hover{color:#ddd;background-color:transparent;text-decoration:none}a:active{color:rgba(221,221,221,.61);background-color:transparent;text-decoration:none}
</style> <link rel="shortcut icon"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAkNJREFUOE+lUstO21AUnHNsF0V+0EXVivAXfAe7qlL7EZEcQ5cQ8nCICbDJF7Trvhas6YbyDdBu2hSk7kihscK1fU91HRKKaFf1xhrP8ejMnCH850P/+v/cC2qcqw4gsGD3Hk/G23+bvSdw7nk1K887BeCQ4AGMAiEjcGaB7gndEfhRqdRQSC9ncQikAVisAWGBFggR5QvQ7UcTNd9mLvDdC2p2rhIN2G4U/vRbneyynzhps70oAPlhNPLjZna1v4/xVmtQHU8tzQXO3CCk4nrPD8MLN+6qd8ef8erwBKvH750XK1Xy4li9/fQFrw9PAGSDg8azuwJDN6jbuep7a+GFF3ezN0en5fDq8Qfn+UqVgjhW5bePpwCKwUHj6a2ACY7zrCdCC34UjrzutjLZiQC/kh0HlyPyu9tKzM4iGPf7uG5sDEwWpYWvrh85RZYAYAIp7+XayNtqytXeLqWbjUUNcLC+fuG2mpLu7tPl5sZDAnpLk0mzFDir+BFJlkCECaKFuSBYSlA4pLWtiRjEygIyErFzyIKjreYTlbZKgaHrRlzoHotweXeAhEhIxPBTDBhQYgEYhNbybINhxY1sbSwwkbHOZrzs3VRmjmnOk6bOkrqxMHT9yCqyxNybAFMg1mWRBGYlg2eboOSFGdT+IwM3Eil6zBwXZF1xkSWkOa6qtHleceuQvC+g4pZXiaOt9jyDb24Q2qKC5XTSvrlK3ZHMW04nLdMPKtQOMzoGTzPz69YNP2vi7D11ftvQWYCzyt7jfwO10TQgL5hT6QAAAABJRU5ErkJggg==">
<script type="text/javascript">
function gId(e){return d.getElementById(e)}function cE(e){return d.createElement(e)}var d=document
</script> </head> <body> <body> <div class="top-part"> <div
style="display:flex;justify-content:center"> <h1
style="display:flex;align-items:center"> <svg
style="width:36px;height:36px;margin-right:6px" viewBox="0 0 32 32"><path
fill="#003fff" d="M6 22h8v4H6zM14 14h4v8h-4zM18 10h4v8h-4zM22 6h8v4h-8z"/></svg>
WLED Pixel Art Converter </h1> </div> <h2>
Convert image to WLED JSON (pixel art on WLED matrix)</h2> <p> <table
id="fieldTable" style="width:100%;table-layout:fixed;align-content:center"> <tr>
<td style="vertical-align:middle"> <label for="ledSetupSelector">Led setup:
</label> </td> <td class="adaptiveTD"> <select id="ledSetupSelector"
class="mainSelector"> <option value="matrix" selected="selected">2D Matrix
</option> <option value="r2l">Serpentine, first row right to left &lt;-</option>
<option value="l2r">Serpentine, first row left to right -&gt;</option>
</select> </td> </tr> <tr> <td style="vertical-align:middle"> <label
for="formatSelector">Output format:</label> </td> <td class="adaptiveTD">
<select id="formatSelector" class="mainSelector"> <option value="wled"
selected="selected">WLED JSON</option> <option value="curl">CURL</option>
<option value="ha">Home Assistant YAML</option> </select> </td> </tr> <tr> <td
style="vertical-align:middle"> <label for="colorFormatSelector">
Color code format:</label> </td> <td class="adaptiveTD"> <select
id="colorFormatSelector" class="mainSelector"> <option value="hex"
selected="selected">HEX (&quot;f4f4f4&quot;)</option> <option value="dec">
DEC (244,244,244)</option> </select> </td> </tr> <tr> <td
style="vertical-align:middle"> <label for="addressingSelector">Addressing:
</label> </td> <td class="adaptiveTD"> <select id="addressingSelector"
class="mainSelector"> <option value="hybrid" selected="selected">
Hybrid (&quot;f0f0f0&quot;,10, 17, &quot;f4f4f4&quot;)</option> <option
value="range">Range (10, 17, &quot;f4f4f4&quot;)</option> <option
value="single">Single (&quot;f4f4f4&quot;)</option> </select> </td> </tr> <tr>
<td style="vertical-align:middle"> <label for="brightnessNumber">Brightness:
</label> </td> <td
style="vertical-align:middle;display:flex;align-items:center"> <input
type="range" id="brightnessNumber" min="1" max="255" value="128"> <span
id="brightnessValue">128</span> </td> </tr> <tr> <td
style="vertical-align:middle"> <label for="colorLimitNumber">
Max no of colors/JSON:</label> </td> <td
style="vertical-align:middle;display:flex;align-items:center"> <input
type="range" id="colorLimitNumber" min="1" max="512" value="256"> <span
id="colorLimitValue">256</span> </td> </tr> <tr class="ha-hide"> <td
style="vertical-align:middle"> <label for="haID">HA Device ID:</label> </td> <td
class="adaptiveTD"> <input class="fullTextField" type="text" id="haID"
value="pixel_art_controller_001"> </td> </tr> <tr class="ha-hide"> <td
style="vertical-align:middle"> <label for="haUID">HA Device Unique ID:</label>
</td> <td class="adaptiveTD"> <input class="fullTextField" type="text"
id="haUID" value="pixel_art_controller_001a"> </td> </tr> <tr class="ha-hide">
<td style="vertical-align:middle"> <label for="haName">HA Device Name:</label>
</td> <td class="adaptiveTD"> <input class="fullTextField" type="text"
id="haName" value="Pixel Art Kitchen"> </td> </tr> <tr> <td
style="vertical-align:middle"> <label for="curlUrl">Device IP/host name:</label>
</td> <td class="adaptiveTD"> <input class="fullTextField" type="text"
id="curlUrl" value> </td> </tr> <tr> <td style="vertical-align:middle"> <label
for="targetSegment">Target segment id:</label> </td> <td class="adaptiveTD">
<input class="flxTFld" type="number" id="segID" value="0" min="0" max="63">
<select id="targetSegment" class="adaptiveSelector"> </select> <div
id="getSegmentsDiv" class="segmentsDiv"></div> </td> </tr> </table> <table
class="scaleTableClass" id="scaleTable"
style="width:100%;table-layout:fixed;align-content:center"> <tr> <td
style="vertical-align:middle"> <div id="scaleDiv"> <svg
style="width:36px;height:36px" viewBox="0 0 24 24" onclick="switchScale()"
cursor="pointer"><path fill="currentColor"
d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5M7 15a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3z"/>
</svg> &nbsp;Scale image </div> </td> <td style="vertical-align:middle"> <div
id="sizeDiv" style="display:none"> <label for="sizeX">W : </label> &nbsp;<input
class="sizeInputFields" type="number" id="sizeX" min="1" value="16">
&nbsp;&nbsp;&nbsp; <label for="sizeY">H : </label> &nbsp;<input
class="sizeInputFields" type="number" id="sizeY" min="1" value="16"> </div>
</td> </tr> </table> </p> <p> <label for="file-picker"> <div id="drop-zone">
Drop image here <br>or <br> Click to select a file </div> </label> </p> <p>
<input type="file" id="file-picker" style="display:none"> </p><div
style="width:100%;text-align:center"> <img id="preview"
style="display:none;margin:0 auto" src="data:text/html;base64,"> </div> <div
id="raw-image-container" style="display:none"> <img id="image"
src="data:text/html;base64," alt="RawImage image"> </div> <p></p> <div
id="image-container" style="display:none"> <div id="image-info"
style="display:none"></div> <textarea id="JSONled" readonly="readonly">
</textarea> </div> <div id="button-container" style="display:none"> <button
id="copyJSONledbutton" class="buttonclass"></button> <div id="gap1" class="gap">
</div> <button id="sendJSONledbutton" class="buttonclass"></button> </div> <div>
<h3><div id="version">Version 1.0.8</div>&nbsp;-&nbsp; <a
href="https://github.com/werkstrom/WLED-PixelArtConverter/blob/main/README.md"
target="_blank">Help/About</a></h3> </div> </div> <div id="bottom-part"
style="display:none" class="bottom-part"></div> <canvas id="pixelCanvas">
</canvas> <script type="text/javascript">
for(var gurl=gId("curlUrl"),szX=gId("sizeX"),szY=gId("sizeY"),szDiv=gId("sizeDiv"),prw=gId("preview"),sID=gId("segID"),JLD=gId("JSONled"),tSg=gId("targetSegment"),brgh=gId("brightnessNumber"),seDiv=gId("getSegmentsDiv"),cjb=gId("copyJSONledbutton"),frm=gId("formatSelector"),cLN=gId("colorLimitNumber"),haIDe=gId("haID"),haUe=gId("haUID"),haNe=gId("haName"),aS=gId("addressingSelector"),cFS=gId("colorFormatSelector"),lSS=gId("ledSetupSelector"),imin=gId("image-info"),imcn=gId("image-container"),bcn=gId("button-container"),im=gId("image"),scDiv=gId("scaleDiv"),w=window,canvas=gId("pixelCanvas"),brgV=gId("brightnessValue"),cLV=gId("colorLimitValue"),httpArray=[],fileJSON="",hideableRows=d.querySelectorAll(".ha-hide"),i=0;i<hideableRows.length;i++)hideableRows[i].classList.add("hide");var accentColor="#eee",accentTextColor="#777",prsCol="#ccc",greenColor="#056b0a",redColor="#6b050c",scaleToggleOffd="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M7,15A3,3 0 0,1 4,12A3,3 0 0,1 7,9A3,3 0 0,1 10,12A3,3 0 0,1 7,15Z",scaleToggleOnd="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z",sSg=gId("getSegmentsSVGpath")
</script> <script type="text/javascript">
function getPixelRGBValues(e){httpArray=[],fileJSON=`{"on":true,"bri":${brgh.value},"seg":{"id":${tSg.value},"i":[`;let t=0;t="flex"==tSg.style.display?tSg.value:sID.value;const l=parseInt(cLN.value);let n=!1,a=-1;a=frm.selectedIndex;const i=frm.options[a].value;a=lSS.selectedIndex;const o=lSS.options[a].value;a=cFS.selectedIndex;let s=!0;"dec"==cFS.options[a].value&&(s=!1),a=aS.selectedIndex;let r=!0;"single"==aS.options[a].value?r=!1:"hybrid"==aS.options[a].value&&(n=!0);let u="",d="",c='"',h='"';s||(c="[",h="]");let p=!1,f="";var g=cE("canvas"),m=g.getContext("2d",{willReadFrequently:!0}),v=new Image;v.src=e,v.onload=function(){let e=scDiv.children[0].children[0].getAttribute("fill"),a=szX.value,y=szY.value;(e!=accentColor||a<1||y<1)&&(a=v.width,y=v.height,(v.width>512||v.height>512)&&(a=16,y=16)),g.width=a,g.height=y,f="<p>Width: "+a+", Height: "+y+" (make sure this matches your led matrix setup)</p>",m.drawImage(v,0,0,a,y);var S=m.getImageData(0,0,a,y).data,I=[];let $=1;"l2r"==o&&($=0);for(var w=0;w<S.length;w+=4){var b=S[w],x=S[w+1],N=S[w+2],T=S[w+3];let e=w/4,t=Math.floor(e/a),l=e;if("matrix"==o);else if((t+$)%2==0);else{l=t*a+(a-1-(l-t*a))}I.push([b,x,N,T,l,e,t])}I.sort((e,t)=>e[5]-t[5]);let O=[...I];O.sort((e,t)=>e[4]-t[4]);let A="",D=-1,R=O.length,j=0,C=[];for(let e=0;e<R;e++){let t=O[e],a=t[0],i=t[1],o=t[2],u=t[3],d="",f=-1;if(r)if(D<0&&(D=e),e<R-1){let t=O[e+1];t[0]==a&&t[1]==i&&t[2]==o||(f=e+1,d=D==e&&n?""==A?e+",":"":D+","+f+",")}else f=e+1,d=D+1==f&&n?""==A?e+",":"":D+","+f+",";else""==A&&(A=e),D=e,f=e;if(u<255&&(p=!0),f>-1){let t=a+","+i+","+o;if(s){const[e,l,n]=[a,i,o];t=""+[e,l,n].map(e=>e.toString(16).padStart(2,"0")).join("")}A+=d+c+t+h,fileJSON=A+d+c+t+h,j+=1,j%l==0||e==R-1?(C.push(A),A=""):A+=",",D=-1}}A="";for(let e=0;e<C.length;e++){let l=`{"on":true,"bri":${brgh.value},"seg":{"id":${t},"i":[${C[e]}]}}`;httpArray.push(l);let n=`curl -X POST "http://${gurl.value}/json/state" -d '${l}' -H "Content-Type: application/json"`;e>0&&(A+="\n<NEXT COMMAND (multiple commands not supported in API/preset setup)>\n",u+=" && "),A+=l,u+=n}d=`#Uncomment if you don't allready have these defined in your switch section of your configuration.yaml \n#- platform: command_line \n #switches: \n ${haIDe.value} \n friendly_name: ${haNe.value} \n unique_id: ${haUe.value} \n command_on: > \n ${u} \n command_off: > \n curl -X POST "http://${gurl.value}/json/state" -d '{"on":false}' -H "Content-Type: application/json"`,JLD.value="wled"==i?A:"curl"==i?u:"ha"==i?d:"ERROR!/n"+i+" is an unknown format.",fileJSON+="]}}";let _=imin,H=imin;p&&(f+="<p><b>WARNING!</b> Transparency info detected in image. Transparency (alpha) has been ignored. To ensure you get the result you desire, use only solid colors in your image.</p>"),_.innerHTML=f,H.style.display="block",drawBoxes(I,a,y)}}
</script> <script type="text/javascript">
function drawBoxes(t,e,a){var i=window,n=canvas.getContext("2d",{willReadFrequently:!0});i.innerHeight<i.innerWidth?canvas.width=Math.floor(.98*i.innerHeight):canvas.width=Math.floor(.98*i.innerWidth);let l=Math.floor(canvas.width/e),h=(i.innerWidth-e*l)/2;canvas.height=l*a+10;for(let i=0;i<a;i++)for(let a=0;a<e;a++){let h=t[i*e+a],r="rgb("+h[0]+", "+h[1]+", "+h[2]+")",d="rgb(128,128,128)";n.fillStyle=r,n.fillRect(a*l,i*l,l,l),n.strokeStyle="#888888",n.lineWidth=1,n.strokeRect(a*l,i*l,l,l),n.font="10px Arial",n.fillStyle=d,n.textAlign="center",n.textBaseline="middle",n.fillText(h[4]+1,a*l+l/2,i*l+l/2)}var r=n.getImageData(0,0,canvas.width,canvas.height);n.clearRect(0,0,canvas.width,canvas.height),canvas.width=i.innerWidth,n.putImageData(r,h,0)}
</script> <script type="text/javascript">
let devMode=!1;gurl.value=location.host;const urlParams=new URLSearchParams(window.location.search);function gen(){if((szX.value>0&&szY.value>0||"none"==szDiv.style.display)&&gurl.value.length>0&&"none"!=prw.style.display){let e=prw.src;if(isValidBase64Gif(e))im.src=e,getPixelRGBValues(e),imcn.style.display="block",bcn.style.display="";else{let t="<p><b>WARNING!</b> File does not appear to be a valid image</p>";imin.innerHTML=t,imin.style.display="block",imcn.style.display="none",JLD.value="",devMode&&console.log("The string '"+e+"' is not a valid base64 image.")}}if(gurl.value.length>0)gId("sSg").setAttribute("fill",accentColor);else{gId("sSg").setAttribute("fill",accentTextColor);let e=tSg;e.style.display="none",e.innerHTML="",sID.style.display="flex"}}async function postPixels(){let e=gId("sendSvgP");e.setAttribute("fill",prsCol);let t=!1;for(let e of httpArray)try{devMode&&console.log(e),devMode&&console.log(e.length);const t=await fetch("http://"+gId("curlUrl").value+"/json/state",{method:"POST",headers:{"Content-Type":"application/json"},body:e}),n=await t.json();devMode&&console.log(n)}catch(e){console.error(e),t=!0}t?(e.setAttribute("fill",redColor),setTimeout((function(){e.setAttribute("fill",accentTextColor)}),1e3)):(e.setAttribute("fill",greenColor),setTimeout((function(){e.setAttribute("fill",accentColor)}),1e3))}gurl.value.length<1&&(gurl.value="Missing_Host"),cjb.addEventListener("click",async()=>{let e=JLD;e.select();try{await navigator.clipboard.writeText(e.value)}catch(e){try{await d.execCommand("copy")}catch(e){console.error("Failed to copy text: ",e)}}}),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),tSg.addEventListener("change",()=>{sop=tSg.options[tSg.selectedIndex],szX.value=sop.dataset.x,szY.value=sop.dataset.y,gen()}),gId("sendJSONledbutton").addEventListener("click",async()=>{"https:"===window.location.protocol?alert("Will only be available when served over http (or WLED is run over https)"):postPixels()}),brgh.oninput=()=>{brgV.textContent=brgh.value;let e=100*parseInt(brgh.value)/255;var t=`linear-gradient(90deg, #bbb ${e}%, #333 ${e}%)`;brgh.style.backgroundImage=t},cLN.oninput=()=>{let e=cLN;cLV.textContent=e.value;let t=100*parseInt(e.value)/512;var n=`linear-gradient(90deg, #bbb ${t}%, #333 ${t}%)`;e.style.backgroundImage=n},frm.addEventListener("change",()=>{for(var e=0;e<hideableRows.length;e++)hideableRows[e].classList.toggle("hide","ha"!==frm.value),gen()});const dropZone=gId("drop-zone"),filePicker=gId("file-picker"),preview=prw;function zoneClicked(e){e.preventDefault(),filePicker.click()}function dragEnter(e){e.preventDefault(),this.classList.add("drag-over")}function dragOver(e){e.preventDefault()}function dropped(e){e.preventDefault(),this.classList.remove("drag-over");updatePreview(e.dataTransfer.files[0])}function filePicked(e){updatePreview(e.target.files[0])}function updatePreview(e){const t=new FileReader;t.onload=()=>{preview.src=t.result,prw.style.display=""},t.readAsDataURL(e)}function isValidBase64Gif(e){return!0}dropZone.addEventListener("dragenter",dragEnter),dropZone.addEventListener("dragover",dragOver),dropZone.addEventListener("drop",dropped),dropZone.addEventListener("click",zoneClicked),filePicker.addEventListener("change",filePicked);for(var hideableRows=d.querySelectorAll(".ha-hide"),i=0;i<hideableRows.length;i++)hideableRows[i].classList.add("hide");function switchScale(){let e=scDiv.children[0].children[0],t=e.getAttribute("fill"),n="";t===accentColor?(t=accentTextColor,n=scaleToggleOffd,szDiv.style.display="none"):(t=accentColor,n=scaleToggleOnd,szDiv.style.display=""),e.setAttribute("fill",t),e.setAttribute("d",n),gen()}function generateSegmentOptions(e){tSg.innerHTML="";for(var t=0;t<e.length;t++){var n=cE("option");n.value=e[t].value,n.text=e[t].text,n.dataset.x=e[t].x,n.dataset.y=e[t].y,tSg.appendChild(n),0===t&&(n.selected=!0,szX.value=n.dataset.x,szY.value=n.dataset.y)}}async function getSegments(){if(cv=gurl.value,cv.length>0)try{var e=[];const n=await fetch("http://"+cv+"/json/state");let l=(await n.json()).seg.map(e=>({id:e.id,n:e.n,xs:e.start,xe:e.stop,ys:e.startY,ye:e.stopY}));for(var t=0;t<l.length;t++)e.push({value:l[t].id,text:l[t].n+" (index: "+l[t].id+")",x:l[t].xe-l[t].xs,y:l[t].ye-l[t].ys});generateSegmentOptions(e),tSg.style.display="flex",sID.style.display="none",gId("sSg").setAttribute("fill",greenColor),setTimeout((function(){gId("sSg").setAttribute("fill",accentColor)}),1e3)}catch(e){console.error(e),gId("sSg").setAttribute("fill",redColor),setTimeout((function(){gId("sSg").setAttribute("fill",accentColor)}),1e3),tSg.style.display="none",sID.style.display="flex"}else gId("sSg").setAttribute("fill",redColor),setTimeout((function(){gId("sSg").setAttribute("fill",accentTextColor)}),1e3),tSg.style.display="none",sID.style.display="flex"}function generateSegmentArray(e){for(var t=[],n=0;n<e;n++)t.push({value:n,text:"Segment index "+n});return t}frm.addEventListener("change",()=>{for(var e=0;e<hideableRows.length;e++)hideableRows[e].classList.toggle("hide","ha"!==frm.value)});var segmentData=generateSegmentArray(10);generateSegmentOptions(segmentData),seDiv.innerHTML='<svg id=getSegmentsSVG style="width:36px;height:36px;cursor:pointer" viewBox="0 0 24 24" onclick="getSegments()"><path id=sSg fill="currentColor" d="M6.5 20Q4.22 20 2.61 18.43 1 16.85 1 14.58 1 12.63 2.17 11.1 3.35 9.57 5.25 9.15 5.68 7.35 7.38 5.73 9.07 4.1 11 4.1 11.83 4.1 12.41 4.69 13 5.28 13 6.1V12.15L14.6 10.6L16 12L12 16L8 12L9.4 10.6L11 12.15V6.1Q9.1 6.45 8.05 7.94 7 9.43 7 11H6.5Q5.05 11 4.03 12.03 3 13.05 3 14.5 3 15.95 4.03 17 5.05 18 6.5 18H18.5Q19.55 18 20.27 17.27 21 16.55 21 15.5 21 14.45 20.27 13.73 19.55 13 18.5 13H17V11Q17 9.8 16.45 8.76 15.9 7.73 15 7V4.68Q16.85 5.55 17.93 7.26 19 9 19 11 20.73 11.2 21.86 12.5 23 13.78 23 15.5 23 17.38 21.69 18.69 20.38 20 18.5 20M12 11.05Z" /></svg>',cjb.innerHTML='<svg class="svg-icon" style="width:36px;height:36px" viewBox="0 0 24 24"> <path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z" /> </svg>&nbsp; Copy to clipboard',gId("sendJSONledbutton").innerHTML='<svg class="svg-icon" style="width:36px;height:36px" viewBox="0 0 24 24"> <path id=sendSvgP fill="currentColor" d="M6.5 20Q4.22 20 2.61 18.43 1 16.85 1 14.58 1 12.63 2.17 11.1 3.35 9.57 5.25 9.15 5.88 6.85 7.75 5.43 9.63 4 12 4 14.93 4 16.96 6.04 19 8.07 19 11 20.73 11.2 21.86 12.5 23 13.78 23 15.5 23 17.38 21.69 18.69 20.38 20 18.5 20H13Q12.18 20 11.59 19.41 11 18.83 11 18V12.85L9.4 14.4L8 13L12 9L16 13L14.6 14.4L13 12.85V18H18.5Q19.55 18 20.27 17.27 21 16.55 21 15.5 21 14.45 20.27 13.73 19.55 13 18.5 13H17V11Q17 8.93 15.54 7.46 14.08 6 12 6 9.93 6 8.46 7.46 7 8.93 7 11H6.5Q5.05 11 4.03 12.03 3 13.05 3 14.5 3 15.95 4.03 17 5.05 18 6.5 18H9V20M12 13Z" /> </svg>&nbsp; Send to device',gurl.value.length>0&&gId("sSg").setAttribute("fill",accentColor)
</script> </body> </body></html>