Files
seweb/client/jsFiles/SEAWebClientGroup.js
2025-05-02 10:55:53 +02:00

826 lines
29 KiB
JavaScript

var writePermission = false;
var showParams = false;
var showConsole = false;
var prompt = false // True while a prompt is opened.
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// COMMUNICATION
function getGroup(s, name) {
reqJSON(s, "http://" + hostPort + "/getblock?path=" + name
+ "&id=" + clientID, successHandler, errorHandler);
}
function sendCommand(s, command) {
reqJSON(s, "http://" + hostPort + "/sendcommand?command=" + encodeURIComponent(command)
+ "&id=" + clientID, successHandler, errorHandler);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// GROUP
function createContent(message) {
// Depending on the message received from the server the content of the
// group is created dynamically. Handles draw-message.
var content = document.createElement('div');
content.classList.add("content");
// Process components of the message
for (var i = 0; i < message.components.length; i++) {
var component = message.components[i];
if (!("title" in component))
component.title = component.name;
if (!("command" in component))
component.command = component.name;
if (message.title == 'modules') {
let row = createRowForModules(component);
content.appendChild(row);
} else {
let row = createRowForParameters(component);
content.appendChild(row);
}
}
return content;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// ROW
function createRowForModules(component) {
let left = createLeftColumnForModules(component);
left.id = component.name;
left.setAttribute('name', 'component.title');
let right = createRightColumnForModules(component);
let row = appendToContent(left, right);
row.onclick = function () {
getGroup(s, component.title);
}
row.classList.add('row-clickable');
return row;
}
function createRowForParameters(component) {
let left = createLeftColumnForParameters(component);
let right = createRightColumnForParameters(component);
return appendToContent(left, right);
}
function appendToContent(left, right) {
let row = document.createElement('div');
row.classList.add("row");
row.appendChild(left);
row.appendChild(right);
return row;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// LEFT COLUMN
function createLeftColumnForModules(component) {
var left = document.createElement('span');
left.classList.add('col-left');
if (component.statusname) {
left.appendChild(createStatusIcon(component));
}
let modules_title = document.createElement('span');
modules_title.classList.add('modules-title');
modules_title.innerHTML = component.title;
if (component.type == 'pushbutton') {
modules_title.classList.add('push-button');
if (writePermission == true) {
modules_title.classList.add('push-button-active');
}
modules_title.onclick = function () {
if (writePermission == true) {
let row = button.closest('div');
row.classList.add('row-waiting-for-answer');
sendCommand(s, component.command);
}
}
}
left.appendChild(modules_title);
if (component.statusname) {
let status_info = document.createElement('span');
status_info.classList.add('status-info');
status_info.setAttribute('name', component.title + '-info');
left.appendChild(status_info);
}
if (component.info) {
let icon_info = createInfoIcon(component);
left.appendChild(icon_info);
left.appendChild(createInfoBox(component));
}
return left;
function createStatusIcon(component) {
let icon_status = document.createElement('img');
icon_status.setAttribute('src', 'res/icon_status.png');
icon_status.setAttribute('name', component.title + ':status');
icon_status.classList.add('icon-modules', 'icon-status');
return icon_status;
}
function createInfoIcon(component) {
let icon_info = document.createElement('img');
icon_info.setAttribute('src', 'res/icon_info.png');
icon_info.classList.add('icon-modules', 'icon-info');
if (isTouchDevice) {
icon_info.onclick = function (event) {
event.stopPropagation()
icon_info.nextSibling.classList.toggle("info-box-visible-by-click");
}
}
return icon_info;
}
function createInfoBox(component) {
// Creates info-box, which isn't visible by default but can be displayed.
let info_box = document.createElement('span');
info_box.classList.add("info-box");
info_box.innerHTML = '<b>' + component.title + '</b>: ' + component.info;
return info_box;
}
}
function createLeftColumnForParameters(component) {
let left = document.createElement('span');
left.classList.add('col-left');
if (component.type == 'pushbutton') {
left.appendChild(createPushButton (component));
} else {
left.innerHTML = component.title;
}
return left;
function createPushButton (component) {
let button = document.createElement('span');
button.classList.add('push-button');
if (writePermission == true) {
button.classList.add('push-button-active');
}
button.innerHTML = component.title;
button.onclick = function () {
if (writePermission == true) {
let row = button.closest('div');
row.classList.add('row-waiting-for-answer');
sendCommand(s, component.command);
}
}
return button;
}
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// RIGHT COLUMN
function createRightColumnForModules(component) {
var right = document.createElement('span');
right.classList.add('col-right', 'col-right-modules');
right.appendChild(createValue(component));
if (component.targetname) {
if (component.type == 'input' ||
component.type == 'checkbox' ||
component.type == 'enum'
) {
let input_element = createType(component);
let icon_edit = createIconEdit(input_element);
right.appendChild(icon_edit);
right.appendChild(input_element);
}
}
return right;
}
function createRightColumnForParameters(component) {
let right = document.createElement('span');
right.classList.add('col-right-parameters');
right.appendChild(createValue(component));
if (component.type == 'input' ||
component.type == 'checkbox' ||
component.type == 'enum'
) {
let input_element = createType(component);
let icon_edit = createIconEdit(input_element);
right.appendChild(icon_edit);
right.appendChild(input_element);
}
return right;
}
function createValue (component) {
let value = document.createElement('span');
value.classList.add('col-right-value');
value.setAttribute('name', component.name);
value.__ctype__ = 'rdonly';
return value;
}
function createIconEdit (input_element) {
let icon_edit = document.createElement('img');
icon_edit.setAttribute('src', 'res/icon_edit.png');
icon_edit.classList.add('icon-modules', 'icon-edit');
if (writePermission == false) {
icon_edit.classList.add('icon-edit-hidden');
}
icon_edit.onclick = function (event) {
event.stopPropagation()
let is_hidden = input_element.classList.contains('input-element-hidden');
hideInputElements();
if (is_hidden) {
input_element.classList.remove('input-element-hidden');
icon_edit.setAttribute('src', 'res/icon_edit_close.png');
} else {
icon_edit.setAttribute('src', 'res/icon_edit.png');
}
}
return icon_edit;
}
function createType (component) {
let input_element;
switch (component.type) {
case 'enum':
input_element = createEnum(component);
input_element.classList.add('input-element', 'input-element-hidden');
break;
case 'input':
input_element = createInputText(component);
input_element.classList.add('input-element', 'input-element-hidden');
break;
case 'checkbox':
input_element = createCheckbox(component);
input_element.classList.add('input-element', 'input-element-hidden');
break;
}
return input_element;
}
/* ---------------------------------------------------------------------------------- */
// input elements
function createInputText(component) {
// Creates row-element containing input-item.
var input = createInputElement(component, 'input', 'input-text');
input.type = "text";
input.style.width = "100px";
input.onclick = function (e) {
e.stopPropagation();
}
// Prevent updates, while user is changing textfield
input.addEventListener("focus", function(evt) {
let elm = evt.target;
setTimeout(function(){elm.setSelectionRange(0, elm.value.length);},0);
});
input.onkeydown = function (e) {
if (e.key == "Escape") {
// User decided to cancel
let input = e.target;
input.value = input.oldValue;
resizeTextfield(input);
var row = input.closest('div');
row.classList.remove('row-waiting-for-answer');
hideInputElements();
}
}
input.onfocus = function () {
input.oldValue = input.value;
if (isTouchDevice)
setTimeout(function () {
posTextfield(s, left);
}, 1);
}
var form = document.createElement('form');
form.onsubmit = function (e) {
e.preventDefault();
var row = form.closest('div');
row.classList.add('row-waiting-for-answer');
// Request for command
input.actualValue = input.value;
if (component.targetname) {
sendCommand(s, component.targetname + " " + input.value);
} else {
sendCommand(s, component.name + " " + input.value);
}
row.classList.add('row-waiting-for-answer');
input.blur();
hideInputElements();
};
form.appendChild(input);
form.appendChild(createSubmitButton());
return form;
}
function createCheckbox(component) {
// Creates row-element containing checkbox-item
var input = createInputElement(component, 'input', 'parameter-checkbox');
input.type = "checkbox";
input.onclick = function (e) {
e.stopPropagation;
}
var form = document.createElement('form');
form.onsubmit = function (e) {
e.preventDefault();
var row = form.closest('div');
row.classList.add('row-waiting-for-answer');
sendCommand(s, component.command + " " + input.checked);
hideInputElements();
};
form.appendChild(input);
form.appendChild(createSubmitButton());
return form;
}
function createEnum(component) {
// Creates row-element containing dropdown-selection.
var buttons = component.enum_names;
var select = createInputElement(component, 'select', 'select-params');
for (var i = 0; i < buttons.length; i++) {
var option = document.createElement('option');
option.type = "enum";
option.classList.add("option-params");
option.value = buttons[i].value;
option.appendChild(document.createTextNode(buttons[i].title));
select.add(option);
}
select.oninput = function () {
let row = select.closest('div');
row.classList.add('row-waiting-for-answer');
let index = select.value - 1;
console.log('send', buttons[index].title);
sendCommand(s, component.command + " " + select.value);
// hideInputElements();
};
select.onfocus = function () {
// select.oldIndex = select.selectedIndex;
console.log(select.selectedValue);
}
var right = document.createElement('span');
right.appendChild(select);
return right;
}
function createInputElement(component, tag='span', cls='col-right-modules') {
var input_element = document.createElement(tag);
input_element.classList.add('col-right');
if (cls)
input_element.classList.add(cls);
if (component.targetname) {
input_element.setAttribute('name', component.targetname);
} else {
input_element.setAttribute('name', component.name);
}
// Add DOM-property
input_element.__ctype__ = component.type;
return input_element;
}
function createSubmitButton () {
let submit_btn = document.createElement('input');
submit_btn.setAttribute('type', 'image');
submit_btn.classList.add('icon-modules', 'icon-okay');
submit_btn.setAttribute('src', 'res/icon_okay.png');
submit_btn.onclick = function (e) {
e.stopPropagation();
}
return submit_btn;
}
/* ---------------------------------------------------------------------------------- */
// Hides all input elements (input text, pushbotton, enum, checkbox)
// Changes all iconEditClose (cross) back to iconEdit (pen)
function hideInputElements(){
let input_elements = document.getElementsByClassName('input-element');
for (let i = 0; i < input_elements.length; i++) {
input_elements[i].classList.add('input-element-hidden');
}
let array_icon_edit = document.getElementsByClassName('icon-edit');
for (let i = 0; i < array_icon_edit.length; i++) {
array_icon_edit[i].setAttribute('src', 'res/icon_edit.png');
}
}
function resizeTextfield(input) {
if (input.value.length > input.size * 12 / 20) {
var str0 = window.getComputedStyle(input).fontSize;
var str1 = str0.substring(0, str0.length - 2);
if (input.value.length < 43) {
input.style.width = input.value.length * str1 * 12 / 20 + "px";
}
} else {
input.style.width = "100px";
}
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// CONTENT
function appendToGridElement(s, title, type, content) {
let panel = document.createElement('div');
panel.classList.add("panel");
titlewrapper = document.createElement('span');
titlewrapper.innerHTML = title;
panel.appendChild(titlewrapper);
let gridContainer = document.createElement('div');
gridContainer.classList.add("grid-container");
// Store type so it can be found easiely later.
gridContainer.slideType = type;
gridContainer.appendChild(panel);
gridContainer.appendChild(content);
let gridelements = document.getElementsByClassName('grid-element');
gridelements[s].innerHTML = "";
gridelements[s].appendChild(gridContainer);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* ---------------------------------------------------------------------------------- */
// obsolete...
// function createPushbutton_row(component) {
// // Creates row-element containing a push button
// var name = component.name;
// var command = component.command;
// var left = createTitle(component);
// left.id = component.name;
// left.name = component.title;
// var right = createInputElement(component);
// right.classList.add("push-button");
// row = appendToContent(left, right);
// right.onclick = function () {
// if (writePermission) {
// var row = left.parentNode;
// right.style.backgroundColor = "orangered";
// // Request for command
// sendCommand(s, command);
// } else {
// prompt = true;
// alertify.confirm("", "You are connected with <b>" + clientTitle
// + "</b>. <br>"
// + "Are you sure you want to modify things here?",
// function () {
// // User decided to proceed.
// writePermission = true;
// writePermissionTimeout = setTimeout(function () {
// writePermission = false;
// }, 3600000);
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// // Request for command
// sendCommand(s, command);
// prompt = false;
// }, function () {
// // User decided to cancel
// prompt = false;
// });
// }
// }
// row.classList.add("row");
// return row;
// }
// function create_input_row(component) {
// // Creates row-element containing input-item.
// var name = component.name;
// var command = component.command;
// var left = createTitle(component);
// var input = createInputElement(component, 'input', 'input-text');
// input.type = "text";
// input.style.width = "100px";
// input.addEventListener("focus", function(evt) {
// let elm = evt.target;
// setTimeout(function(){elm.setSelectionRange(0, elm.value.length);},0);
// });
// input.onkeydown = function (e) {
// if (e.which === 27 || e.key == "Escape") {
// // User decided to cancel
// input.value = intput.oldValue;
// resizeTextfield(input);
// var row = left.parentNode;
// row.style.backgroundColor = "white";
// }
// }
// input.onfocus = function () {
// input.oldValue = input.value;
// if (isTouchDevice)
// setTimeout(function () {
// posTextfield(s, left);
// }, 1);
// }
// input.onblur = function () {
// if (prompt) {
// return false;
// }
// var row = left.parentNode;
// var value = input.value;
// let oldValue = 'oldValue' in input ? input.oldValue : value;
// if (!('actualValue' in input)) input.actualValue = oldValue;
// actualValue = input.actualValue;
// if (value == actualValue || value == oldValue ||
// parseFloat(value) == parseFloat(actualValue) || parseFloat(value) == parseFloat(oldValue)) {
// input.value = actualValue;
// // nothing to do.
// row.style.backgroundColor = "white";
// return false;
// }
// // User changed value and moved focus to other object.
// alertify.confirm("", "You changed a field without pressing the return key.<br>"
// + "Hint: press ESC for leaving a field unchanged.<b>"
// + "You are connected with <b>" + clientTitle + "</b>.<br>"
// + "Are you sure you want to change the value of<br><b>"
// + name + "</b> from <b>" + actualValue
// + "</b> to <b>" + value + "</b>?", function () {
// // User decided to proceed.
// writePermission = true;
// writePermissionTimeout = setTimeout(function () {
// writePermission = false;
// }, 3600000);
// row.style.backgroundColor = "orangered";
// // Request for command
// sendCommand(s, command + " " + value);
// resizeTextfield(input);
// prompt = false;
// }, function () {
// // User decided to cancel
// input.value = input.actualValue;
// resizeTextfield(input);
// row.style.backgroundColor = "white";
// prompt = false;
// });
// }
// var form = document.createElement('form');
// form.onsubmit = function (e) {
// e.preventDefault();
// if (writePermission) {
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// // Request for command
// input.actualValue = input.value;
// sendCommand(s, name + " " + input.value);
// input.blur();
// } else {
// var value = input.value
// prompt = true;
// alertify.confirm("", "You are connected with <b>" + clientTitle
// + "</b>. <br>"
// + "Are you sure you want to modify things here?",
// function () {
// // User decided to proceed.
// writePermission = true;
// writePermissionTimeout = setTimeout(function () {
// writePermission = false;
// }, 3600000);
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// input.actualValue = value;
// // Request for command
// sendCommand(s, command + " " + value);
// resizeTextfield(input);
// prompt = false;
// }, function () {
// // User decided to cancel
// input.value = input.oldValue;
// resizeTextfield(input);
// prompt = false;
// });
// }
// };
// form.appendChild(input);
// var right = createInputElement(component);
// right.appendChild(form);
// return appendToContent(left, right);
// function posTextfield(s, left) {
// if (debug_group_daniel) {
// console.log("%cfunction: posTextfield", "color:white;background:salmon");
// }
// // var content = swiper[s].slides[swiper[s].activeIndex].childNodes[1];
// // var row = left.parentNode;
// // content.scrollTop = row.offsetTop - 30;
// // ---------------------> Not working anymore since swiper was removed!!!
// }
// }
// function createCheckbox_row(component) {
// // Creates row-element containing checkbox-item
// var command = component.command;
// var left = createTitle(component);
// var input = createInputElement(component, 'input', 'parameter-checkbox');
// input.type = "checkbox";
// input.onkeyup = function (e) {
// if (e.keyCode === 32) {
// handleCheckbox();
// }
// }
// var label = document.createElement('label');
// label.for = input;
// label.classList.add("parameter-label");
// label.onclick = function () {
// handleCheckbox();
// }
// function handleCheckbox() {
// if (writePermission) {
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// if (input.checked) {
// var value = "0";
// input.checked = false;
// } else {
// var value = "1";
// input.checked = true;
// }
// // Request for command
// sendCommand(s, command + " " + value);
// } else {
// alertify.confirm("", "You are connected with <b>" + clientTitle
// + "</b>. <br>"
// + "Are you sure you want to modify things here?",
// function () {
// // User decided to proceed.
// writePermission = true;
// writePermissionTimeout = setTimeout(function () {
// writePermission = false;
// }, 3600000);
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// if (input.checked) {
// var value = "0";
// input.checked = false;
// } else {
// var value = "1";
// input.checked = true;
// }
// // Request for command
// sendCommand(s, command + " " + value);
// }, function () {
// // User decided to cancel
// });
// }
// };
// var right = document.createElement('span');
// right.classList.add("col-right");
// right.appendChild(input);
// right.appendChild(label);
// return appendToContent(left, right);
// }
// function createEnum_row(component) {
// // Creates row-element containing dropdown-selection.
// var name = component.name;
// var command = component.command;
// var buttons = component.enum_names;
// var left = createTitle(component);
// var select = createInputElement(component, 'select', 'select-params');
// select.onfocus = function () {
// select.oldIndex = select.selectedIndex;
// }
// select.oninput = function () {
// if (writePermission && component.title != "device config") {
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// // Request for command
// sendCommand(s, command + " " + this.value);
// } else {
// alertify.confirm("", "You are connected with <b>" + clientTitle
// + "</b>. <br>"
// + "Are you sure you want to modify things here?",
// function () {
// // User decided to proceed.
// writePermission = true;
// writePermissionTimeout = setTimeout(function () {
// writePermission = false;
// }, 3600000);
// var row = left.parentNode;
// row.style.backgroundColor = "orangered";
// // Request for command
// sendCommand(s, command + " " + select.value);
// }, function () {
// // User decided to cancel
// select.value = select.options[select.oldIndex].value
// });
// }
// };
// for (var i = 0; i < buttons.length; i++) {
// var option = document.createElement('option');
// option.type = "enum";
// option.classList.add("option-params");
// option.value = buttons[i].value;
// option.appendChild(document.createTextNode(buttons[i].title));
// select.add(option);
// }
// select.style.display = "none";
// var right = document.createElement('span');
// right.classList.add("col-right");
// right.appendChild(select);
// return appendToContent(left, right);
// }
// ...obsolete
/* ---------------------------------------------------------------------------------- */
// The following two functions seem unreachable
/* ########## Is this function used? How? Where? ########## */
// function create_group_row(component) {
// // Creates row-element containing link.
// var title = component.title;
// var row = document.createElement('row');
// row.id = component.name;
// row.name = title;
// row.classList.add("row");
// row.tabIndex = "0";
// console.log('createGroupRow');
// row.onclick = function () {
// var slideNames = getSlideNames();
// slideNames[0] = component.name;
// document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
// history.pushState({func: "gotoGroups", funarg: slideNames.join("%20")}, document.title, "#" + slideNames.join("%20"));
// getGroup(s, component.name);
// }
// if (title === "console" || title === "device config") {
// row.classList.add("row");
// row.innerHTML = "console";
// }
// row.innerHTML = title;
// return row;
// }
/* ########## Is this function used? How? Where? ########## */
// function create_rdonly_row(component) {
// // Creates row-element containing link AND read-only-item.
// var link = component.link;
// if (!link) // simple rdonly
// return appendToContent(createTitle(component),
// createInputElement(component));
// // with link
// var left = document.createElement('a');
// left.innerHTML = component.title;
// console.log('ccc')
// left.id = component.name;
// row = appendToContent(left, createInputElement(component));
// row.onclick = function () {
// this.style.backgroundColor = "orangered";
// left.click();
// }
// if (link.charAt(0) == ':') {
// left.href = "http://" + location.hostname + link + "/";
// } else {
// left.href = link;
// }
// row.classList.add("row");
// return row;
// }