bc18eda336
Text field accessible by edit icon Replaced magnifier with iconfont Use woff2 font format Fix scaled checkboxes visible in UI settings header
247 lines
8.1 KiB
HTML
247 lines
8.1 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head lang="en">
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=500">
|
|
<title>UI Settings</title>
|
|
<script>
|
|
var d = document;
|
|
var initial_ds, initial_st;
|
|
var sett = null;
|
|
var l = {
|
|
"comp":{
|
|
"labels":"Show button labels",
|
|
"colors":{
|
|
"LABEL":"Color selection methods",
|
|
"picker": "Color Wheel",
|
|
"rgb": "RGB sliders",
|
|
"quick": "Quick color selectors",
|
|
"hex": "HEX color input"
|
|
},
|
|
"pcmbot": "Show bottom tab bar in PC mode",
|
|
"pid": "Show preset IDs",
|
|
"seglen": "Set segment length instead of stop LED",
|
|
"css": "Enable custom CSS",
|
|
"hdays": "Enable custom Holidays list"
|
|
},
|
|
"theme":{
|
|
"alpha": {
|
|
"bg":"Background opacity",
|
|
"tab":"Button opacity"
|
|
},
|
|
"bg":{
|
|
"url":"BG image URL",
|
|
"random":"Random BG image"
|
|
},
|
|
"color":{
|
|
"bg":"BG HEX color"
|
|
}
|
|
}
|
|
};
|
|
function gId(s)
|
|
{
|
|
return d.getElementById(s);
|
|
}
|
|
function isObject(item) {
|
|
return (item && typeof item === 'object' && !Array.isArray(item));
|
|
}
|
|
function set(path, obj, val) {
|
|
var tar = obj;
|
|
var pList = path.split('_');
|
|
var len = pList.length;
|
|
for(var i = 0; i < len-1; i++) {
|
|
var elem = pList[i];
|
|
if( !tar[elem] ) tar[elem] = {}
|
|
tar = tar[elem];
|
|
}
|
|
tar[pList[len-1]] = val;
|
|
}
|
|
var timeout;
|
|
function showToast(text, error = false)
|
|
{
|
|
var x = gId("toast");
|
|
x.innerHTML = text;
|
|
x.className = error ? "error":"show";
|
|
clearTimeout(timeout);
|
|
x.style.animation = 'none';
|
|
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
|
|
}
|
|
function addRec(s, path = "", label = null)
|
|
{
|
|
var str = "";
|
|
for (i in s)
|
|
{
|
|
var fk = path + (path?'_':'') + i;
|
|
if (isObject(s[i])) {
|
|
if (label && label[i] && label[i]["LABEL"]) str += `<h3>${label[i]["LABEL"]}</h3>`;
|
|
str += addRec(s[i], fk, label? label[i] : null);
|
|
} else {
|
|
var lb = fk;
|
|
if (label && label[i]) lb = label[i];
|
|
else if (s[i+'LABEL']) lb = s[i+'LABEL'];
|
|
if (i.indexOf('LABEL') > 0) continue;
|
|
var t = typeof s[i];
|
|
if (gId(fk)) { //already exists
|
|
if(t === 'boolean')
|
|
{
|
|
gId(fk).checked = s[i];
|
|
} else {
|
|
gId(fk).value = s[i];
|
|
}
|
|
if (gId(fk).previousElementSibling.matches('.l')) {
|
|
gId(fk).previousElementSibling.innerHTML = lb;
|
|
}
|
|
} else {
|
|
if(t === 'boolean')
|
|
{
|
|
str += `${lb}: <input class="agi cb" type="checkbox" id=${fk} ${s[i]?"checked":""}><br>`;
|
|
} else if (t === 'number')
|
|
{
|
|
str += `${lb}: <input class="agi" type="number" id=${fk} value=${s[i]}><br>`;
|
|
} else if (t === 'string')
|
|
{
|
|
str += `${lb}:<br><input class="agi" id=${fk} value=${s[i]}><br>`;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
function genForm(s) {
|
|
var str = "";
|
|
str = addRec(s,"",l);
|
|
|
|
gId('gen').innerHTML = str;
|
|
}
|
|
function GetLS()
|
|
{
|
|
sett = localStorage.getItem('wledUiCfg');
|
|
if (!sett) gId('lserr').style.display = "inline";
|
|
try {
|
|
sett = JSON.parse(sett);
|
|
} catch (e) {
|
|
sett = {};
|
|
gId('lserr').style.display = "inline";
|
|
gId('lserr').innerHTML = "⚠ Settings JSON parsing failed. (" + e + ")";
|
|
}
|
|
genForm(sett);
|
|
gId('dm').checked = (gId('theme_base').value === 'light');
|
|
}
|
|
|
|
function SetLS()
|
|
{
|
|
var l = d.querySelectorAll('.agi');
|
|
for (var i = 0; i < l.length; i++) {
|
|
var e = l[i];
|
|
var val = e.classList.contains('cb') ? e.checked : e.value;
|
|
set(e.id, sett, val);
|
|
console.log(`${e.id} set to ${val}`);
|
|
}
|
|
try {
|
|
localStorage.setItem('wledUiCfg', JSON.stringify(sett));
|
|
gId('lssuc').style.display = "inline";
|
|
} catch (e) {
|
|
gId('lssuc').style.display = "none";
|
|
gId('lserr').style.display = "inline";
|
|
gId('lserr').innerHTML = "⚠ Settings JSON saving failed. (" + e + ")";
|
|
}
|
|
}
|
|
|
|
function Save() {
|
|
SetLS();
|
|
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st) d.Sf.submit();
|
|
}
|
|
|
|
function S()
|
|
{
|
|
GetV();
|
|
initial_ds = d.Sf.DS.value;
|
|
initial_st = d.Sf.ST.checked;
|
|
GetLS();
|
|
}
|
|
function H()
|
|
{
|
|
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");
|
|
}
|
|
function B()
|
|
{
|
|
window.open("/settings","_self");
|
|
}
|
|
function UI()
|
|
{
|
|
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
|
var f = gId('theme_base');
|
|
if (f) f.value = (gId('dm').checked) ? 'light':'dark';
|
|
}
|
|
|
|
// random BG image
|
|
function setRandomBg() {
|
|
if (gId("theme_bg_random").checked) {
|
|
gId("theme_bg_url").value = "https://picsum.photos/1920/1080";
|
|
} else {
|
|
gId("theme_bg_url").value = "";
|
|
}
|
|
|
|
}
|
|
function checkRandomBg() {
|
|
if (gId("theme_bg_url").value === "https://picsum.photos/1920/1080") {
|
|
gId("theme_bg_random").checked = true;
|
|
} else {
|
|
gId("theme_bg_random").checked = false;
|
|
}
|
|
}
|
|
function uploadFile(fO,name) {
|
|
var req = new XMLHttpRequest();
|
|
req.addEventListener('load', function(){showToast(this.responseText)});
|
|
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
|
req.open("POST", "/upload");
|
|
var formData = new FormData();
|
|
formData.append("data", fO.files[0], name);
|
|
req.send(formData);
|
|
fO.value = '';
|
|
return false;
|
|
}
|
|
function GetV(){var d=document;}
|
|
</script>
|
|
<style>@import url("style.css");</style>
|
|
</head>
|
|
<body onload="S()">
|
|
<form id="form_s" name="Sf" method="post">
|
|
<div style="position:sticky;top:0;background-color:#222;z-index:1;">
|
|
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
|
<button type="button" onclick="B()">Back</button><button type="button" onclick="Save()">Save</button><br>
|
|
<span id="lssuc" style="color:green; display:none">✔ Local UI settings saved!</span>
|
|
<span id="lserr" style="color:red; display:none">⚠ Could not access local storage. Make sure it is enabled in your browser.</span><hr>
|
|
</div>
|
|
<h2>Web Setup</h2>
|
|
Server description: <input name="DS" maxlength="32"><br>
|
|
Sync button toggles both send and receive: <input type="checkbox" name="ST"><br>
|
|
<i>The following UI customization settings are unique both to the WLED device and this browser.<br>
|
|
You will need to set them again if using a different browser, device or WLED IP address.<br>
|
|
Refresh the main UI to apply changes.</i><br>
|
|
|
|
<div id="gen">Loading settings...</div>
|
|
|
|
<h3>UI Appearance</h3>
|
|
<span class="l"></span>: <input type="checkbox" id="comp_labels" class="agi cb"><br>
|
|
<span class="l"></span>: <input type="checkbox" id="comp_pcmbot" class="agi cb"><br>
|
|
<span class="l"></span>: <input type="checkbox" id="comp_pid" class="agi cb"><br>
|
|
<span class="l"></span>: <input type="checkbox" id="comp_seglen" class="agi cb"><br>
|
|
I hate dark mode: <input type="checkbox" id="dm" onchange="UI()"><br>
|
|
<span id="idonthateyou" style="display:none"><i>Why would you? </i>🥺<br></span>
|
|
<span class="l"></span>: <input type="number" min=0.0 max=1.0 step=0.01 id="theme_alpha_tab" class="agi"><br>
|
|
<span class="l"></span>: <input type="number" min=0.0 max=1.0 step=0.01 id="theme_alpha_bg" class="agi"><br>
|
|
<span class="l"></span>: <input id="theme_color_bg" maxlength="9" class="agi"><br>
|
|
<span class="l">BG image URL</span>: <input id="theme_bg_url" class="agi" oninput="checkRandomBg()"><br>
|
|
<span class="l">Random BG image</span>: <input type="checkbox" id="theme_bg_random" class="agi cb" onchange="setRandomBg()"><br>
|
|
<input id="theme_base" class="agi" style="display:none">
|
|
<span class="l"></span>: <input type="checkbox" id="comp_css" class="agi cb"><br>
|
|
<div id="skin">Custom CSS: <input type="file" name="data" accept=".css"> <input type="button" value="Upload" onclick="uploadFile(d.Sf.data,'/skin.css');"><br></div>
|
|
<span class="l"></span>: <input type="checkbox" id="comp_hdays" class="agi cb"><br>
|
|
<div id="holidays">Holidays: <input type="file" name="data2" accept=".json"> <input type="button" value="Upload" onclick="uploadFile(d.Sf.data2,'/holidays.json');"><br></div>
|
|
<div id="toast"></div>
|
|
<hr><button type="button" onclick="B()">Back</button><button type="button" onclick="Save()">Save</button>
|
|
</form>
|
|
</body>
|
|
</html> |