Skip to content

Commit

Permalink
Support for recursive select options
Browse files Browse the repository at this point in the history
index.js
- ppf: reset logNode if > 64000
- add isObject function, use in receiveData, changeHTML Coord3D
- changeHTML options: remove old options and opgroups, add recursive findOptions function

SysModSystem
- heartbeat shows ip the first minute

SysModUI
- add findOptionsText (recursive)
  • Loading branch information
ewoudwijma committed May 9, 2024
1 parent 4879437 commit 34514cd
Show file tree
Hide file tree
Showing 6 changed files with 1,317 additions and 1,215 deletions.
78 changes: 63 additions & 15 deletions data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function ppf() {
let logNode = gId("log");
let sep = "";
if (logNode) {
if (logNode.value.length > 64000) logNode.value = ""; //reset if too big
// console.log("conslog", theArgs);
for (var i = 0; i < arguments.length; i++) {
// console.log(arguments[i]);
Expand Down Expand Up @@ -606,7 +607,7 @@ function varRemoveValuesForRow(variable, rowNr) {
function receiveData(json) {
// console.log("receiveData", json);

if (Object.keys(json)) {
if (isObject(json)) {
for (let key of Object.keys(json)) {
let value = json[key];

Expand Down Expand Up @@ -817,25 +818,61 @@ function changeHTML(variable, commandJson, rowNr = UINT8_MAX) {
selectNodes.push(node);
}

// console.log("commandJson.options", variable.id, commandJson.options);
for (let selectNode of selectNodes) {
//remove all old options first
var index = 0;
while (selectNode.options && selectNode.options.length > 0) {
selectNode.remove(0);

//remove options
for (var i = selectNode.length-1; i > 0; i--) {
selectNode.options[i] = null;
}
for (var value of commandJson.options) {
let optNode = cE("option");
if (Array.isArray(value)) {
optNode.value = value[0];
optNode.text = value[1];
// remove the optgroups and their children if still exists
var optgroup=selectNode.getElementsByTagName('optgroup')
for (var i=optgroup.length-1;i>=0;i--) selectNode.removeChild(optgroup[i])

var index = 0;

//go recursively through the objects
function findOptions(group, option, depth = 0) {
if (isObject(option)) {
for (let key of Object.keys(option)) { // for each group
if (depth > 0) {
let optNode = cE("option"); // no optgroups in optgroups so create on same level
optNode.label = key;
group.appendChild(optNode);
findOptions(group, option[key], depth+1);
}
else {
let optGroup = cE("optgroup");
optGroup.label = key;
group.appendChild(optGroup);
findOptions(optGroup, option[key], depth+1);
}
}
}
else if (Array.isArray(option)) {
for (let subOption of option) {
if (Array.isArray(subOption)) { //array of arrays: // for key values like ip nr and name
let optNode = cE("option");
optNode.value = subOption[0];
optNode.text = subOption[1];
selectNode.appendChild(optNode);
}
else
findOptions(group, subOption, depth); //recursive call were subOption is object
}
}
else {
optNode.value = index;
optNode.text = value;
let optNode = cE("option");
optNode.value = index++;
optNode.text = "---------".substring(0, depth-1) + option;
group.appendChild(optNode);
}
selectNode.appendChild(optNode);
index++;
}
findOptions(selectNode, commandJson.options); //recursively go through all the options

// console.log("Select options", selectNode, selectNode.options);

}

variable.options = commandJson.options;
Expand Down Expand Up @@ -863,7 +900,7 @@ function changeHTML(variable, commandJson, rowNr = UINT8_MAX) {
//add each row
let newRowNr = 0;
for (var row of commandJson.value) {
if (row) { //not null, pnlTbl sent value:[null]... tbd: check why
if (row) { //not null, e.g. fixTbl sent value:[null]... tbd: check why
genTableRowHTML(variable, node, newRowNr);
let colNr = 0;
for (let columnVar of variable.n) {
Expand Down Expand Up @@ -970,7 +1007,7 @@ function changeHTML(variable, commandJson, rowNr = UINT8_MAX) {
if (Array.isArray(commandJson.value) && rowNr != UINT8_MAX)
value = commandJson.value[rowNr];

if (Object.keys(value)) {
if (isObject(value)) {
if (variable.ro) {
let sep = "";
node.textContent = "";
Expand All @@ -983,6 +1020,7 @@ function changeHTML(variable, commandJson, rowNr = UINT8_MAX) {
let index = 0;
for (let key of Object.keys(value)) {
let childNode = node.childNodes[index++];
if (!childNode) console.log("dev Coord3D no child", variable, node, value, key, value[key], index);
childNode.value = value[key];
childNode.dispatchEvent(new Event("input")); // triggers addEventListener('input',...). now only used for input type range (slider), needed e.g. for qlc+ input
}
Expand Down Expand Up @@ -1659,4 +1697,14 @@ function previewBoard(canvasNode, buffer) {
index++;
}
}
}

// Utility function
//https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
function isObject(val) {
if (Array.isArray(val)) return false;
if (val === null) { return false;}
return ( (typeof val === 'function') || (typeof val === 'object'));

//or return obj === Object(obj); //true for arrays.???
}
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ build_flags =
${STARBASE_USERMOD_E131.build_flags}
; ${STARBASE_USERMOD_HA.build_flags}
-DAPP=StarBase
-DVERSION=24050213 ; Date and time (GMT!)
-DVERSION=24050907 ; Date and time (GMT!)
-DPIOENV=$PIOENV
lib_deps =
${StarBase.lib_deps}
Expand Down
7 changes: 6 additions & 1 deletion src/Sys/SysModSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,12 @@ void SysModSystem::loop10s() {
if (psramFound()) {
ui->callVarFun(mdl->findVar("psram"));
}
ppf("❤️"); //heartbeat

//heartbeat
if (millis() < 60000)
ppf("❤️ %s\n", WiFi.localIP().toString().c_str()); // show IP the first minute
else
ppf("❤️");
}

//replace code by sentence as soon it occurs, so we know what will happen and what not
Expand Down
37 changes: 36 additions & 1 deletion src/Sys/SysModUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,42 @@ class SysModUI: public SysModule {
return web->getResponseObject()[mdl->varID(var)]["options"];
}
void clearOptions(JsonObject var) {
web->getResponseObject().remove(mdl->varID(var));
web->getResponseObject()[mdl->varID(var)].remove("options");
}

//find options text in a hierarchy of options (groupName and optionName as pointers? String is already a pointer?)
void findOptionsText(JsonObject var, uint8_t value, JsonString *groupName, JsonString *optionName) {
uint8_t startValue = 0;
bool optionsExisted = !web->getResponseObject()[mdl->varID(var)]["options"].isNull();
JsonArray options = getOptions(var);
if (!findOptionsTextRec(options, &startValue, value, groupName, optionName))
ppf("findOptions select option not found %d %s %s\n", value, (*groupName).isNull()?"X":(*groupName).c_str(), (*optionName).isNull()?"X":(*optionName).c_str());
if (!optionsExisted)
clearOptions(var);
}

bool findOptionsTextRec(JsonVariant options, uint8_t * startValue, uint8_t value, JsonString *groupName, JsonString *optionName, JsonString parentGroup = JsonString()) {
if (options.is<JsonArray>()) { //array of options
for (JsonVariant option : options.as<JsonArray>()) {
if (findOptionsTextRec(option, startValue, value, groupName, optionName, parentGroup))
return true;
}
}
else if (options.is<JsonObject>()) { //group
for (JsonPair pair: options.as<JsonObject>()) {
if (findOptionsTextRec(pair.value(), startValue, value, groupName, optionName, parentGroup.isNull()?pair.key():parentGroup)) //send the master level group name only
return true;
}
} else { //individual option
if (*startValue == value) {
*groupName = parentGroup;
*optionName = options.as<JsonString>();
ppf("Found %d=%d ? %s . %s\n", *startValue, value, (*groupName).isNull()?"":(*groupName).c_str(), (*optionName).isNull()?"":(*optionName).c_str());
return true;
}
(*startValue)++;
}
return false;
}

private:
Expand Down
2 changes: 1 addition & 1 deletion src/Sys/SysStarJson.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class StarJson {

//reads from file until all vars have been found (then stops reading)
//returns false if not all vars to look for are found
bool deserialize(bool lazy) {
bool deserialize(bool lazy = false) {
f.read(&character, sizeof(byte));
while (f.available() && (!foundAll || !lazy))
next();
Expand Down
Loading

0 comments on commit 34514cd

Please sign in to comment.