WLED/wled00/data/settings_um.htm
Blaz Kristan 81182bb125 Added parsing usermod settings parameters.
Added nested object handling in usermod settings parameters.
2021-06-25 23:20:01 +02:00

155 lines
6.0 KiB
HTML

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=500">
<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 t,c;
switch (typeof o) {
case "boolean":
t = "checkbox"; c = o ? `checked value="on"` : ""; break;
case "number":
if (isF(o)) {
c = `value="${parseFloat(o)}" step="0.01"`;
t = "float";
} else {
c = `value="${parseInt(o,10)}"`;
if (f==="pin") c += ' max="39" min="-1"';
t = "int";
}
break;
case "string":
t = "text"; c = `value="${o}"`; break;
default:
t = "text"; c = `value="${o}"`; 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="off">`;
else if (!a) urows += `<input type="hidden" name="${k}_${f}${a?"[]":""}" value="${t}">`;
urows += `<input type="${t==="float"||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>
<link href="/skin.css" rel="stylesheet">
</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">&#10004; Configuration saved!</span>
<span id="lserr" style="color:red; display:none">&#9888; 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>