beremiz

SVGHMI: JsonTable now use intermediate variables again to address JSON data without duplicating code or referencing. Using intermediate variables also alows to check for availability of data and stop evaluating early if data is missing. Finally added complete roundtrip example to illustrate use of JSonTable to display "alarms" collected in python from changes on PLC boolean variables.
// widget_slider.ysl2
template "widget[@type='Slider']", mode="widget_class"
||
class SliderWidget extends Widget{
frequency = 5;
range = undefined;
fi = undefined;
drag = false;
enTimer = false;
dispatch(value) {
if(this.value_elt)
this.value_elt.textContent = String(value);
this.update_DOM(value, this.handle_elt);
}
last_drag = false;
update_DOM(value, elt){
let [min,max,start,totallength] = this.range;
let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
let tip = this.range_elt.getPointAtLength(length);
elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
if(this.setpoint_elt != undefined){
if(this.last_drag!= this.drag){
if(this.drag){
this.setpoint_elt.setAttribute("style", this.setpoint_style);
}else{
this.setpoint_elt.setAttribute("style", "display:none");
}
this.last_drag = this.drag;
}
}
}
on_release(evt) {
window.removeEventListener("touchmove", this.on_bound_drag, true);
window.removeEventListener("mousemove", this.on_bound_drag, true);
window.removeEventListener("mouseup", this.bound_on_release, true)
window.removeEventListener("touchend", this.bound_on_release, true);
window.removeEventListener("touchcancel", this.bound_on_release, true);
if(this.drag){
this.drag = false;
}
this.update_position(evt);
}
on_drag(evt){
if(this.enTimer && this.drag){
this.update_position(evt);
//reset timer
this.enTimer = false;
setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
}
}
update_position(evt){
var html_dist = 0;
//calculate size of widget in html
var range_borders = this.range_elt.getBoundingClientRect();
var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
//get range and mouse coordinates
var mouseX = undefined;
var mouseY = undefined;
if (evt.type.startsWith("touch")){
mouseX = Math.ceil(evt.touches[0].clientX);
mouseY = Math.ceil(evt.touches[0].clientY);
}
else{
mouseX = evt.pageX;
mouseY = evt.pageY;
}
//get handle distance from mouse position
if (minX > mouseX && minY < mouseY){
html_dist = 0;
}
else if (maxX < mouseX && maxY > mouseY){
html_dist = range_length;
}
else{
// calculate distace
if(this.fi > 0.7){
html_dist = (minY - mouseY)/Math.sin(this.fi);
}
else{
html_dist = (mouseX - minX)/Math.cos(this.fi);
}
//check if in range
if (html_dist > range_length){
html_dist = range_length;
}
else if (html_dist < 0){
html_dist = 0;
}
}
this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]);
this.apply_hmi_value(0, this.svg_dist);
// update ghost cursor
if(this.setpoint_elt != undefined){
this.request_animate();
}
}
animate(){
this.update_DOM(this.svg_dist, this.setpoint_elt);
}
on_select(evt){
this.drag = true;
this.enTimer = true;
window.addEventListener("touchmove", this.on_bound_drag, true);
window.addEventListener("mousemove", this.on_bound_drag, true);
window.addEventListener("mouseup", this.bound_on_release, true)
window.addEventListener("touchend", this.bound_on_release, true);
window.addEventListener("touchcancel", this.bound_on_release, true);
this.update_position(evt);
}
init() {
let min = this.min_elt ?
Number(this.min_elt.textContent) :
this.args.length >= 1 ? this.args[0] : 0;
let max = this.max_elt ?
Number(this.max_elt.textContent) :
this.args.length >= 2 ? this.args[1] : 100;
this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()];
let start = this.range_elt.getPointAtLength(0);
let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength());
this.fi = Math.atan2(start.y-end.y, end.x-start.x);
this.bound_on_select = this.on_select.bind(this);
this.bound_on_release = this.on_release.bind(this);
this.on_bound_drag = this.on_drag.bind(this);
this.element.addEventListener("mousedown", this.bound_on_select);
this.element.addEventListener("touchstart", this.bound_on_select);
if(this.setpoint_elt != undefined){
this.setpoint_style = this.setpoint_elt.getAttribute("style");
this.setpoint_elt.setAttribute("style", "display:none");
}
}
}
||
template "widget[@type='Slider']", mode="widget_defs" {
param "hmi_element";
labels("handle range");
optional_labels("value min max setpoint");
|,
}