154 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html>
 | |
| <head lang="en">
 | |
|     <meta charset="utf-8">
 | |
|     <meta name="viewport" content="width=500">
 | |
|     <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
 | |
|     <title>Usermod Settings</title>
 | |
|     <script>
 | |
|     var d = document;
 | |
|     var umCfg = {};
 | |
|     var pins = [6,7,8,9,10,11];
 | |
|     var pinO = ["rsvd","rsvd","rsvd","rsvd","rsvd","rsvd"], owner;
 | |
|     var loc = false, locip;
 | |
|     var urows;
 | |
|     var numM = 0;
 | |
|     function gId(s) { return d.getElementById(s); }
 | |
|     function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
 | |
|     function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
 | |
|     function B() { window.open("/settings","_self"); }
 | |
|     function S() {
 | |
|         if (window.location.protocol == "file:") {
 | |
|             loc = true;
 | |
|             locip = localStorage.getItem('locIp');
 | |
|             if (!locip) {
 | |
|                 locip = prompt("File Mode. Please enter WLED IP!");
 | |
|                 localStorage.setItem('locIp', locip);
 | |
|             }
 | |
|         }
 | |
|         GetV();
 | |
|         if (numM > 0 || locip) ldS();
 | |
|         else gId("um").innerHTML = "No Usermods installed.";
 | |
|     }
 | |
|     // https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
 | |
|     function isF(n) { return n === +n && n !== (n|0); }
 | |
|     function isI(n) { return n === +n && n === (n|0); }
 | |
|     function check(o,k) {   // input object, pin owner key
 | |
|         var n = o.name.replace("[]","").substr(-3);
 | |
|         if (o.type=="number" && n.substr(0,3)=="pin") {
 | |
|             for (var i=0; i<pins.length; i++) {
 | |
|                 if (k==pinO[i]) continue;
 | |
|                 if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     function getPins(o) {
 | |
|         if (isO(o)) {
 | |
|             for (const [k,v] of Object.entries(o)) {
 | |
|                 if (isO(v)) {
 | |
|                     owner = k;
 | |
|                     getPins(v);
 | |
|                     continue;
 | |
|                 }
 | |
|                 if (k.replace("[]","").substr(-3)=="pin") {
 | |
|                     if (Array.isArray(v)) {
 | |
|                         for (var i=0; i<v.length; i++) if (v[i]>=0) { pins.push(v[i]); pinO.push(owner); }
 | |
|                     } else {
 | |
|                         if (v>=0) { pins.push(v); pinO.push(owner); }
 | |
|                     }
 | |
|                 } else if (Array.isArray(v)) {
 | |
|                     for (var i=0; i<v.length; i++) getPins(v[i]);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     function addField(k,f,o,a=false) {  //key, field, (sub)object, isArray
 | |
|         if (isO(o)) {
 | |
|             for (const [s,v] of Object.entries(o)) {
 | |
|                 // possibility to nest objects (only 1 level)
 | |
|                 if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
 | |
|                 else addField(k,s,v);
 | |
|             }
 | |
|         } else if (Array.isArray(o)) {
 | |
|             for (var j=0; j<o.length; j++) {
 | |
|                 addField(k,f,o[j],true);
 | |
|             }
 | |
|         } else {
 | |
|             var c, t = typeof o;
 | |
|             switch (t) {
 | |
|                 case "boolean":
 | |
|                     t = "checkbox"; c = 'value="true"' + (o ? ' checked' : '');
 | |
|                     break;
 | |
|                 case "number":
 | |
|                     c = `value="${o}"`;
 | |
|                     if (f.substr(-3)==="pin") {
 | |
|                         c += ' max="39" min="-1" class="s"';
 | |
|                         t = "int";
 | |
|                     } else {
 | |
|                         c += ' step="any" class="xxl"';
 | |
|                     }
 | |
|                     break;
 | |
|                 default:
 | |
|                     t = "text"; c = `value="${o}" style="width:250px;"`;
 | |
|                     break;
 | |
|             }
 | |
|             if (k.includes(":")) urows += k.substr(k.indexOf(":")+1);
 | |
|             urows += ` ${f}: `;
 | |
|             // https://stackoverflow.com/questions/11657123/posting-both-checked-and-unchecked-checkboxes
 | |
|             if (t=="checkbox") urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="false">`;
 | |
|             else if (!a)       urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="${t}">`;
 | |
|             urows += `<input type="${t==="int"?"number":t}" name="${k}:${f}${a?"[]":""}" ${c} oninput="check(this,'${k.substr(k.indexOf(":")+1)}')"><br>`;
 | |
|         }
 | |
|     }
 | |
|     function ldS() {
 | |
|         var url = (loc?`http://${locip}`:'') + '/cfg.json';
 | |
|         fetch(url, {
 | |
|             method: 'get'
 | |
|         })
 | |
|         .then(res => {
 | |
|             if (!res.ok) gId('lserr').style.display = "inline";
 | |
|             return res.json();
 | |
|         })
 | |
|         .then(json => {
 | |
|             umCfg = json.um;
 | |
|             getPins(json);
 | |
|             urows="";
 | |
|             if (isO(umCfg)) {
 | |
|                 for (const [k,o] of Object.entries(umCfg)) {
 | |
|                     urows += `<hr><h3>${k}</h3>`;
 | |
|                     addField(k,'unknown',o);
 | |
|                 }
 | |
|             }
 | |
|             if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
 | |
|             gId("um").innerHTML = urows;
 | |
|         })
 | |
|         .catch(function (error) {
 | |
|             gId('lserr').style.display = "inline"
 | |
|             console.log(error);
 | |
|         });
 | |
|     }
 | |
|     function svS(e) {
 | |
|         e.preventDefault();
 | |
|         console.log(d.Sf);
 | |
|         if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
 | |
|     }
 | |
|     function GetV() {}
 | |
|     </script>
 | |
|     <style>@import url("style.css");</style>
 | |
| </head>
 | |
| 
 | |
| <body onload="S()">
 | |
| 	<form id="form_s" name="Sf" method="post" onsubmit="svS(event)">
 | |
| 		<div class="toprow">
 | |
| 		<div class="helpB"><button type="button" onclick="H()">?</button></div>
 | |
| 		<button type="button" onclick="B()">Back</button><button type="submit">Save</button><br>
 | |
| 		<span id="lssuc" style="color:green; display:none">✔ Configuration saved!</span>
 | |
| 		<span id="lserr" style="color:red; display:none">⚠ Could not load configuration.</span><hr>
 | |
| 		</div>
 | |
| 		<h2>Usermod Setup</h2>
 | |
|         <div id="um">Loading settings...</div>
 | |
| 		<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
 | |
| 	</form>
 | |
| </body>
 | |
| 
 | |
| </html> | 
