265 lines
13 KiB
JavaScript
265 lines
13 KiB
JavaScript
class Signals {
|
|
constructor(indicators) {
|
|
this.indicators = indicators;
|
|
this.signals=[];
|
|
}
|
|
// Call to display the 'Create new signal' dialog.
|
|
open_signal_Form() { document.getElementById("new_sig_form").style.display = "grid"; }
|
|
// Call to hide the 'Create new signal' dialog.
|
|
close_signal_Form() { document.getElementById("new_sig_form").style.display = "none"; }
|
|
|
|
request_signals(){
|
|
// Requests a list of all the signals from the server.
|
|
window.UI.data.comms.send_to_app('request', 'signals');
|
|
}
|
|
delete_signal(signal_name){
|
|
// Requests that the server remove a specific signal.
|
|
window.UI.data.comms.send_to_app('delete_signal', signal_name);
|
|
// Get the signal element from the UI
|
|
let child = document.getElementById(signal_name + '_item');
|
|
// Ask the parent of the signal element to remove its child(signal) from the document.
|
|
child.parentNode.removeChild(child);
|
|
}
|
|
i_update(updates){
|
|
// Set local records of incoming signal updates and update the html that displays that info.
|
|
for (let signal in this.signals){
|
|
// Get the new value of the property from the 1st source in this signal from the update.
|
|
let value1 = updates[this.signals[signal].source1].data[0][this.signals[signal].prop1];
|
|
// Update the local record of value1
|
|
this.signals[signal].value1 = value1.toFixed(2);
|
|
if (this.signals[signal].source2 != 'value'){
|
|
// Do the same for the second source if the source isn't a set value.
|
|
let value2 = updates[this.signals[signal].source2].data[0][this.signals[signal].prop2];
|
|
this.signals[signal].value2 = value2.toFixed(2);
|
|
}
|
|
// Update the html element that displays this information.
|
|
document.getElementById(this.signals[signal].name + '_value1').innerHTML = this.signals[signal].value1;
|
|
document.getElementById(this.signals[signal].name + '_value2').innerHTML = this.signals[signal].value2;
|
|
}
|
|
}
|
|
update_signal_states(s_updates){
|
|
for (name in s_updates){
|
|
let id = name + '_state'
|
|
let span = document.getElementById(id);
|
|
span.innerHTML = s_updates[name];
|
|
console.log('state change!');
|
|
console.log(name);
|
|
}
|
|
|
|
}
|
|
set_data(signals){
|
|
// Create a list item for every signal and add it to a UL element.
|
|
var ul = document.getElementById("signal_list");
|
|
|
|
// loop through a provided list of signals and attributes.
|
|
for (let sig in signals){
|
|
|
|
// Create a Json object from each signals.
|
|
// TODO: Clean up this inconsistent code.
|
|
// During initialization this receives the object in string form.
|
|
// when the object is created this function receives an object.
|
|
if (typeof(signals[sig]) == 'string'){
|
|
var obj = JSON.parse(signals[sig]);
|
|
}else {var obj=signals[sig];}
|
|
// Keep a local record of the signals.
|
|
this.signals.push(obj);
|
|
// Define the function that is called when deleting an individual signal.
|
|
let click_func = "window.UI.signals.delete_signal('" + obj.name + "')";
|
|
// create a delete button for every individual signal.
|
|
let delete_btn = '<button onclick="' + click_func + '" style="color:red;">✘</button>';
|
|
|
|
// Put all the attributes into html elements.
|
|
let signal_name = " <span>" + obj.name + ": </span>";
|
|
let signal_state = "<span id='" + obj.name + "_state'>" + obj.state + "</span><br>";
|
|
let signal_source1 = "<span>" + obj.source1 + "(" + obj.prop1 + ") </span>";
|
|
let signal_val1 = "<span id='" + obj.name + "_value1'>" + obj.value1 + "</span>";
|
|
let operator = " " + obj.operator + " ";
|
|
let signal_source2 = "<span>" + obj.source2 + "(" + obj.prop2 + ") </span>";
|
|
let signal_val2 = "<span id='" + obj.name + "_value2'>" + obj.value2 + "</span>";
|
|
|
|
// Stick all the html together.
|
|
let html = delete_btn;
|
|
html += signal_name + signal_state;
|
|
html += signal_source1 + signal_val1;
|
|
html += operator;
|
|
html += signal_source2 + signal_val2;
|
|
|
|
// Create the list item.
|
|
let li = document.createElement("li");
|
|
// Give it an id.
|
|
li.id = obj.name + '_item';
|
|
// Inject the html.
|
|
li.innerHTML= html;
|
|
// And add it the the UL we created earlier.
|
|
ul.appendChild(li);
|
|
}
|
|
}
|
|
|
|
fill_prop(target_id, indctr){
|
|
// arg1: Id of of a selection element.
|
|
// arg2: Name of an indicator
|
|
// Replace the options of an HTML select elements
|
|
// with the properties an indicator object.
|
|
|
|
// Fetch the objects using name and id received.
|
|
var target = document.getElementById(target_id);
|
|
var properties = window.UI.data.indicators[indctr];
|
|
|
|
// Remove any previous options in the select tag.
|
|
removeOptions(target);
|
|
// Loop through each property in the object.
|
|
// Create an option element for each one.
|
|
// Append it to the selection element.
|
|
for(let prop in properties)
|
|
{
|
|
if (prop =='type'|| prop == 'visible' || prop == 'period'){continue;}
|
|
if (prop.substring(0,5) == 'color'){continue;}
|
|
var opt = document.createElement("option");
|
|
opt.innerHTML = prop;
|
|
target.appendChild(opt);
|
|
}
|
|
return;
|
|
function removeOptions(selectElement) {
|
|
var i, L = selectElement.options.length - 1;
|
|
for(i = L; i >= 0; i--) {
|
|
selectElement.remove(i);
|
|
}
|
|
}
|
|
}
|
|
switch_panel(p1,p2){
|
|
// Panel switcher for multi page forms
|
|
// arg1 = target from id
|
|
// arg2 = next target id
|
|
// This function is used in the New Signal dialog in signals
|
|
document.getElementById(p1).style.display='none';
|
|
document.getElementById(p2).style.display='grid';
|
|
}
|
|
|
|
hideIfTrue(firstValue, scndValue, id){
|
|
// Compare first two args and hides an element if they are equal.
|
|
// This function is used in the New Signal dialog in signals
|
|
if( firstValue == scndValue){
|
|
document.getElementById(id).style.display='none';
|
|
}else{
|
|
document.getElementById(id).style.display='block'
|
|
}
|
|
}
|
|
ns_next(n){
|
|
// This function is used in the New Signal dialog in signals
|
|
if (n==1){
|
|
// Check input fields.
|
|
let sigName = document.getElementById('signal_name').value;
|
|
let sigSource = document.getElementById('sig_source').value;
|
|
let sigProp = document.getElementById('sig_prop').value;
|
|
if (sigName == '' ) { alert('Please give the signal a name.'); return; }
|
|
// Populate sig_display
|
|
document.getElementById('sig_display').innerHTML = (sigName + ': {' + sigSource + ':' + sigProp +'}');
|
|
// Popilate Value input
|
|
let indctrVal = document.getElementById(sigSource + '_' + sigProp).value;
|
|
document.getElementById('value').value = indctrVal;
|
|
|
|
this.switch_panel('panel_1','panel_2');
|
|
}
|
|
if (n==2){
|
|
|
|
// Collect all the input fields.
|
|
|
|
let sigName = document.getElementById('signal_name').value; // The name of the New Signal.
|
|
let sigSource = document.getElementById('sig_source').value; // The source(indicator) of the signal.
|
|
let sigProp = document.getElementById('sig_prop').value; // The property to evaluate.
|
|
let sig2Source = document.getElementById('sig2_source').value; // The second source if selected.
|
|
let sig2Prop = document.getElementById('sig2_prop').value; // The second property to evaluate.
|
|
let operator = document.querySelector('input[name="Operator"]:checked').value; // The operator this evaluation will use.
|
|
let range = document.getElementById('rangeVal').value; // The value of any range being evaluated.
|
|
let sigType = document.getElementById('select_s_type').value; // The type of signal value or indicator comparison.
|
|
let value = document.getElementById('value').value; // The input value if it is a value comparison.
|
|
|
|
// Create a string to define the signal.
|
|
|
|
// Include the first indicator source.
|
|
var sig1 = `${sigSource} : ${sigProp}`;
|
|
// If it is a comparison signal include the second indicator source.
|
|
if (sigType == 'Comparison') {
|
|
var sig2 = `${sig2Source} : ${sig2Prop}`;
|
|
}
|
|
// If it is a value signal include the value.
|
|
if (sigType == 'Value') {var sig2 = value;}
|
|
|
|
// If the operator is set to range, include the range value in the string.
|
|
if (operator == '+/-') {
|
|
var operatorStr = `${operator} ${range}`;
|
|
} else{
|
|
var operatorStr = operator;
|
|
}
|
|
|
|
let sigDisplayStr = `(${sigName}) (${sig1}) (${operatorStr}) (${sig2})`;
|
|
|
|
// Get the current realtime values of the sources.
|
|
let sig1_realtime = document.getElementById(sigSource + '_' + sigProp).value;
|
|
|
|
if (sigType == 'Comparison') {
|
|
// If its a comparison get the second value from the second source.
|
|
var sig2_realtime = document.getElementById(sig2Source + '_' + sig2Prop).value;
|
|
}else {
|
|
// If not the second realtime value is literally the value.
|
|
var sig2_realtime = sig2;
|
|
}
|
|
// Populate the signal display field with the string.
|
|
document.getElementById('sig_display2').innerHTML = sigDisplayStr;
|
|
|
|
// Populate the realtime values display.
|
|
let realtime_Str = `(${sigProp} : ${sig1_realtime}) (${operatorStr}) (${sig2_realtime})`;
|
|
document.getElementById('sig_realtime').innerHTML = realtime_Str;
|
|
// Evaluate the signal
|
|
var evalStr;
|
|
if (operator == '=') {evalStr = (sig1_realtime == sig2_realtime);console.log([sig1_realtime, sig2_realtime, operator,evalStr]);}
|
|
if (operator == '>') {evalStr = (sig1_realtime > sig2_realtime);}
|
|
if (operator == '<') {evalStr = (sig1_realtime < sig2_realtime);}
|
|
if (operator == '+/-') {
|
|
evalStr = (Math.abs(sig1_realtime - sig2_realtime) <= range);
|
|
}
|
|
|
|
// Populate the signal eval field with the string.
|
|
document.getElementById('sig_eval').innerHTML = evalStr;
|
|
|
|
// Show the panel
|
|
this.switch_panel('panel_2','panel_3');
|
|
}
|
|
}
|
|
|
|
submitNewSignal(){
|
|
|
|
// Collect all the input fields.
|
|
|
|
var name = document.getElementById('signal_name').value; // The name of the New Signal.
|
|
var source1 = document.getElementById('sig_source').value; // The source(indicator) of the signal.
|
|
var prop1 = document.getElementById('sig_prop').value; // The property to evaluate.
|
|
var source2 = document.getElementById('sig2_source').value; // The second source if selected.
|
|
var prop2 = document.getElementById('sig2_prop').value; // The second property to evaluate.
|
|
var operator = document.querySelector('input[name="Operator"]:checked').value; // The operator this evaluation will use.
|
|
var range = document.getElementById('rangeVal').value; // The value of any range being evaluated.
|
|
var sigType = document.getElementById('select_s_type').value; // The type of signal value or indicator comparison.
|
|
var value = document.getElementById('value').value; // The input value if it is a value comparison.
|
|
var state = false;
|
|
if (sigType == 'Comparison'){
|
|
var source2 = source2;
|
|
var prop2 = prop2;
|
|
}else{
|
|
var source2 = 'value';
|
|
var prop2 = value;
|
|
}
|
|
var value1 = null;
|
|
var value2 = null;
|
|
if (operator == "+/-" ){
|
|
var range = {range : range};
|
|
var data = {name, source1, prop1, operator, source2, prop2, range, state, value1, value2};
|
|
}else{
|
|
var data = {name, source1, prop1, operator, source2, prop2, state, value1, value2};
|
|
}
|
|
/* It may be more maintainable to configure the connection inside the different classes
|
|
than passing functions, references and callbacks around. */
|
|
|
|
window.UI.data.comms.send_to_app( "new_signal", data);
|
|
this.close_signal_Form();
|
|
}
|
|
} |