Se actualizan librerias de RGraph y cambios menores

This commit is contained in:
Exequiel Aramburu 2026-09-27 23:33:38 -03:00
parent 99264aba3d
commit 5221b6fb19
11 changed files with 3751 additions and 3300 deletions

View File

@ -1,4 +1,5 @@
** Mejoras de interfaz y configuración (Septiembre 27, 2026)
+ Se actualizó RGraph 7.01 → 7.21
+ NW.js 0.117.0 centralizado en runtime.json para desarrollo y empaquetado x64.
+ Formulario compartido con controles nativos, validación y aviso de cambios sin guardar.
+ Guardado atómico y POST con confirmación; el núcleo recibe la configuración nueva.

View File

@ -84,7 +84,6 @@
</span>
</nav>
<section id="estado-estacion" class="estado-estacion" aria-label="Estado de la estación"></section>
<br><br>
<div id="superior" class="container">
<div class="row">
<div class="col-2 text-center vertical-align-top">

View File

@ -96,7 +96,7 @@
}
.container {
max-width: 1800px !important;
max-width: 100% !important;
}
h1 {
@ -499,7 +499,6 @@ hr.style18:before {
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}

View File

@ -1,15 +1,16 @@
'version:2025-10-08 (7.01)';
'version:2026-08-11 (7.21)';
//
// o---------------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net/license.html |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
// | free to use and there are no restrictions on what you can use RGraph for! |
// | If the GPL license does not suit you however, then there's an inexpensive |
// | commercial license option available. See the URL above for more details. |
// o---------------------------------------------------------------------------------o
// o---------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. This means |
// | that it's free to use for any purpose. The GPL license does have |
// | consequences on the license of the software that you include it in, |
// | however. If this is not desirable, then there's an inexpensive commercial |
// | license option available. See the RGraph website for more details. |
// o---------------------------------------------------------------------------o
RGraph = window.RGraph || {isrgraph:true,isRGraph: true,rgraph:true};
@ -47,16 +48,16 @@
this.properties =
{
backgroundBarsCount: null,
backgroundBarsColor1: 'rgba(0,0,0,0)',
backgroundBarsColor2: 'rgba(0,0,0,0)',
backgroundBarsColor1: 'transparent',
backgroundBarsColor2: 'transparent',
backgroundGrid: true,
backgroundGridColor: '#ddd',
backgroundGridColor: '#eee',
backgroundGridLinewidth: 1,
backgroundGridHsize: 20,
backgroundGridVsize: 20,
backgroundGridVlines: true,
backgroundGridVlines: false,
backgroundGridHlines: true,
backgroundGridBorder: true,
backgroundGridBorder: false,
backgroundGridAutofit: true,
backgroundGridAutofitAlign: true,
backgroundGridHlinesCount: 5,
@ -115,7 +116,7 @@
labelsAboveUnitsPost:'',
labelsAboveFormatter:null,
yaxis: true,
yaxis: false,
yaxisLinewidth: 1,
yaxisColor: 'black',
yaxisTickmarks: true,
@ -162,7 +163,8 @@
yaxisTitleValign: null,
yaxisTitleAccessible: null,
xaxis: true,
xaxis: false,
xaxisPosition: 'bottom',
xaxisLinewidth: 1,
xaxisColor: 'black',
xaxisTickmarks: true,
@ -235,22 +237,28 @@
titleSubtitleOffsetx: 0,
titleSubtitleOffsety: 0,
colorsStroke: 'rgba(0,0,0,0)',
colors: ['red','#0f0','blue','pink','orange','cyan','black','white','green','magenta'],
colorsStroke: 'transparent',
colors: RGraph.getColors(),
colorsSequential: false,
colorsReverse: false,
grouping: 'grouped',
variant: 'bar',
variantSketchVerticals: true,
variantThreedXaxis: true,
variantThreedYaxis: true,
variantThreedAngle: 0.1,
variantThreedOffsetx: 10,
variantThreedOffsety: 5,
variantThreedXaxisColor: '#ddd',
variantThreedYaxisColor: '#ddd',
variant: 'bar',
variantSketchVerticals: true,
variantThreedXaxis: true,
variantThreedYaxis: true,
variantThreedAngle: 0.1,
variantThreedOffsetx: 10,
variantThreedOffsety: 5,
variantThreedXaxisColor: '#ddd',
variantThreedYaxisColor: '#ddd',
variantDumbbellLinewidth: 8,
variantDumbbellEndTop: true,
variantDumbbellEndBottom: true,
variantDumbbellEndRadius: 13,
variantDumbbellEndTopRadius: null,
variantDumbbellEndBottomRadius: null,
shadow: false,
shadowColor: '#aaa',
@ -284,8 +292,9 @@
tooltipsPointerOffsety: 0,
tooltipsPositionStatic: true,
highlightStroke: 'rgba(0,0,0,0)',
highlightStroke: 'transparent',
highlightFill: 'rgba(255,255,255,0.7)',
highlightFade: true,
key: null,
keyBackground: 'white',
@ -345,17 +354,17 @@
beveled: false,
errorbars: false,
errorbarsColor: 'black',
errorbarsColor: 'black',
errorbarsCapped: true,
errorbarsCappedWidth: 14,
errorbarsCappedWidth: 14,
errorbarsLinewidth: 1,
combinedEffect: null,
combinedEffectOptions: null,
combinedEffectCallback: null,
corners: 'square',
cornersRoundRadius: 10,
corners: 'round',
cornersRoundRadius: 5,
cornersRoundLeft: true,
cornersRoundRight: true,
cornersRoundLeftRadius: null,
@ -363,13 +372,18 @@
responsive: null,
clearto: 'rgba(0,0,0,0)',
clearto: 'transparent',
style: null,
events: {},
clip: null,
scale: true,
scaleFactor: 2,
antialiasTranslate: false
antialiasTranslate: false,
style: []
};
@ -434,6 +448,10 @@
'titleSubtitleOffsety',
'variantThreedOffsetx',
'variantThreedOffsety',
'variantDumbbellLinewidth',
'variantDumbbellEndRadius',
'variantDumbbellEndTopRadius',
'variantDumbbellEndBottomRadius',
'shadowOffsetx',
'shadowOffsety',
'shadowBlur',
@ -674,7 +692,15 @@
//
// Add any CSS that has been specified to the document.
// This is general CSS and does not necessarily have to
// pertain to the canvas tag. It only gets added once
// to the document no matter how many times this draw
// function is called.
//
// Add the CSS to a <style> block in the <head>.
RGraph.addConfigurationBasedCSS(this);
@ -693,8 +719,40 @@
}
// MUST be the THIRD thing done!
if (typeof properties.backgroundImage === 'string') {
if (typeof properties.backgroundImage === 'string' && properties.backgroundImage) {
//
// Install clipping for the background image. This
// is not the main installation of clipping - it's
// just for the background image.
//
// The this.scale2 check means that clipping is only
// installed if that variable is present - ie this
// is most likely a redraw and the necessary things
// have been calculated so clipping can be
// installed correctly.
//
if (!RGraph.isNullish(this.properties.clip) && this.scale2) {
RGraph.clipTo.start(this, this.properties.clip);
}
RGraph.drawBackgroundImage(this);
if (!RGraph.isNullish(this.properties.clip) && this.scale2) {
RGraph.clipTo.end();
}
}
// If 3D is enabled then turn off rounded corners
// because it doesn't look correct.
if (this.properties.variant === '3d' && this.properties.corners === 'round') {
this.properties.corners = 'square'
}
@ -797,10 +855,24 @@
// If a dumbbell chart is being drawn then a few
// properties need to be massaged
if (!this.properties.colorsDumbbell && this.properties.variant === 'dumbbell') {
this.set({
colorsDumbbell: this.get('colors')
});
this.set({
colors: ['#0000']
});
};
//
// Work out the max value
//
if (properties.yaxisScaleMax) {
if (this.properties.yaxisScaleMax) {
this.scale2 = RGraph.getScale({object: this, options: {
'scale.max': properties.yaxisScaleMax,
@ -878,6 +950,12 @@
this.scale2 = RGraph.getScale({object: this, options: {
'scale.max': this.max,
'scale.min': properties.yaxisScaleMin,
@ -928,9 +1006,19 @@
// this.drawAxes();
// this.drawbars();
//} else {
this.drawbars();
this.drawAxes();
this.drawbars();
this.drawAxes();
//}
//
// Draw the dumbbell bars variant Draw this here
// so that the dumbells are drawn over the axes.
//
if (this.properties.variant === 'dumbbell') {
this.drawdumbbell();
}
this.drawLabels();
@ -1092,11 +1180,11 @@
//
if (properties.xaxisLabels && properties.xaxisLabels.length) {
if (typeof properties.xaxisLabels === 'string') {
properties.xaxisLabels = RGraph.arrayPad({
array: [],
length: this.data.length,
value: properties.xaxisLabels
});
properties.xaxisLabels = RGraph.arrayPad(
[],
this.data.length,
properties.xaxisLabels
);
}
// Label substitution
@ -1164,7 +1252,7 @@
RGraph.drawBars(this);
}
var variant = properties.variant;
var variant = this.properties.variant;
//
// Draw the 3D axes is necessary
@ -1300,7 +1388,7 @@
this.context.fillStyle = colors[i];
}
if (variant == 'sketch') {
if (variant === 'sketch') {
this.context.lineCap = 'round';
@ -1360,21 +1448,21 @@
this.context.stroke();
// Regular bar
} else if (variant == 'bar' || variant == '3d' || variant == 'glass' || variant == 'bevel') {
} else if (variant === 'bar' || variant === '3d' || variant === 'glass' || variant === 'bevel' || variant === 'dumbbell') {
if (variant == 'glass') {
RGraph.roundedRect({
context: this.context,
x: x + hmargin,
y: y,
width: barWidth,
height: height,
radius: RGraph.isNumber(properties.cornersRoundRadius) ? properties.cornersRoundRadius : 5,
roundtl: this.data[i] > 0,
roundtr: this.data[i] > 0,
roundbl: this.data[i] < 0,
roundbr: this.data[i] < 0
});
RGraph.roundedRect(
this.context,
x + hmargin,
y,
barWidth,
height,
RGraph.isNumber(properties.cornersRoundRadius) ? properties.cornersRoundRadius : 5,
this.data[i] > 0,
this.data[i] > 0,
this.data[i] < 0,
this.data[i] < 0
);
this.context.stroke();
this.context.fill();
} else {
@ -1546,7 +1634,7 @@ this.context.lineTo(
// Dot chart
} else if (variant == 'dot') {
} else if (variant === 'dot') {
var scaleFactor = RGraph.getScaleFactor(this);
@ -2439,66 +2527,101 @@ this.context.lineTo(
//
// Each object type has its own Highlight() function which highlights the appropriate shape
// Each object type has its own Highlight() function which
// highlights the appropriate shape.
//
// @param object shape The shape to highlight
// @param object shape The shape to highlight.
//
this.highlight = function (shape)
{
if (typeof properties.highlightStyle === 'function') {
(properties.highlightStyle)(shape);
// If the highlightFade property is not set then call
// the highlight function multiple times when the
// globalAlpha is set at varying levels of transparency
// to fade the highlight in. If the variable is set,
// however, then this call is probably a part of said
// highlighting process so don't call ourselves
// again - just highlight the chart.
if (this.properties.highlightFade && !this.highlight.highlighting) {
// Highlight all of the rects except this one - essentially
// an inverted highlight
} else if (typeof properties.highlightStyle === 'string' && properties.highlightStyle === 'invert') {
for (var i=0; i<this.coords.length; ++i) {
if (i !== shape.sequentialIndex) {
this.path(
'b r % % % % s % f %',
this.coords[i][0],this.coords[i][1],this.coords[i][2],this.coords[i][3],
properties.highlightStroke,
properties.highlightFill
);
// Add a variable to the highlight function (this
// function) to indicate that we're currently in
// the process of highlighting.
this.highlight.highlighting = true;
var obj = this;
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 20);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 40);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 60);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 80);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 100);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 120);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 140);
setTimeout(function() {obj.highlight.highlighting = false;}, 400);
return;
}
RGraph.clipTo.callback(this, function (obj)
{
if (typeof obj.properties.highlightStyle === 'function') {
(obj.properties.highlightStyle)(shape);
// Highlight all of the rects except this one - essentially
// an inverted highlight
} else if (typeof obj.properties.highlightStyle === 'string' && obj.properties.highlightStyle === 'invert') {
for (var i=0; i<obj.coords.length; ++i) {
if (i !== shape.sequentialIndex) {
obj.path(
'b r % % % % s % f %',
obj.coords[i][0],obj.coords[i][1],obj.coords[i][2],obj.coords[i][3],
obj.properties.highlightStroke,
obj.properties.highlightFill
);
}
}
}
// Redraw the X axis so the highlight doesn't
// appear over the X axis. But not the X axis
// labels or the title. This is new in
// September 2024.
RGraph.drawXAxis(this, {
labels: false,
title: false
});
} else {
if (properties.grouping === 'stacked' && shape.index === 0 && properties.xaxisPosition === 'bottom') {
this.context.beginPath();
this.context.strokeStyle = properties.highlightStroke;
this.context.fillStyle = properties.highlightFill;
if (properties.corners === 'round') {
this.roundedCornersRect(shape.x,shape.y,shape.width,shape.height);
} else {
this.context.rect(shape.x, shape.y, shape.width, shape.height);
}
this.context.stroke();
this.context.fill();
} else {
// Add the new highlight
RGraph.Highlight.rect(this, shape);
// Redraw the X axis so the highlight doesn't
// appear over the X axis. But not the X axis
// labels or the title. This is new in
// September 2024.
RGraph.drawXAxis(this, {
labels: false,
title: false
});
if (obj.properties.variant !== 'dumbbell') {
RGraph.drawXAxis(obj, {
labels: false,
title: false
});
}
} else {
if (properties.grouping === 'stacked' && shape.index === 0 && obj.properties.xaxisPosition === 'bottom') {
obj.context.beginPath();
obj.context.strokeStyle = obj.properties.highlightStroke;
obj.context.fillStyle = obj.properties.highlightFill;
if (obj.properties.corners === 'round') {
obj.roundedCornersRect(shape.x,shape.y,shape.width,shape.height);
} else {
obj.context.rect(shape.x, shape.y, shape.width, shape.height);
}
obj.context.stroke();
obj.context.fill();
} else {
// Add the new highlight
RGraph.Highlight.rect(obj, shape);
// Redraw the X axis so the highlight doesn't
// appear over the X axis. But not the X axis
// labels or the title. This is new in
// September 2024.
if (obj.properties.variant !== 'dumbbell') {
RGraph.drawXAxis(obj, {
labels: false,
title: false
});
}
}
}
}
}); // End of clipping callback function.
};
@ -2523,13 +2646,19 @@ this.context.lineTo(
mouseXY[1] -= adjustment;
}
var dbEndTopradius = 0;
var dbEndBottomradius = 0;
if (this.properties.variant === 'dumbbell') {
dbEndTopradius = this.properties.variantDumbbellEndTopRadius || this.properties.variantDumbbellEndRadius;
dbEndBottomradius = this.properties.variantDumbbellEndBottomRadius || this.properties.variantDumbbellEndRadius;
}
if (
mouseXY[0] >= properties.marginLeft
&& mouseXY[0] <= (this.canvas.width - properties.marginRight)
&& mouseXY[1] >= properties.marginTop
&& mouseXY[1] <= (this.canvas.height - properties.marginBottom)
mouseXY[0] >= this.properties.marginLeft
&& mouseXY[0] <= (this.canvas.width - this.properties.marginRight)
&& mouseXY[1] >= this.properties.marginTop - dbEndTopradius
&& mouseXY[1] <= (this.canvas.height - this.properties.marginBottom + dbEndBottomradius)
) {
return this;
@ -2679,7 +2808,10 @@ this.context.lineTo(
// Allow for JSON gradients
if (color.match(/^gradient\(({.*})\)$/i)) {
return RGraph.parseJSONGradient({object: this, def: RegExp.$1});
return RGraph.parseJSONGradient({
object: this,
def: RegExp.$1
});
}
@ -3409,7 +3541,7 @@ this.context.lineTo(
// Callback
var opt = arguments[0] || {},
frames = opt.frames || 30,
frames = opt.frames || 60,
frame = 0,
callback = arguments[1] || function () {},
obj = this,
@ -3797,6 +3929,34 @@ this.context.lineTo(
var indexes = RGraph.sequentialIndexToGrouped(opt.index, this.data);
var values = this.data[indexes[0]];
// This makes dumbbell charts work correctly
//
// Match the current index with the correct group/index
// values by looking through the coords2 array using the
// current mouse position.
if (this.properties.variant === 'dumbbell') {
var mouseXY = RGraph.getMouseXY(window.event);
outer:
for (var i=0; i<this.coords2.length; ++i) {
for (var j=0; j<this.coords2[i].length; ++j) {
if (
mouseXY[0] > this.coords2[i][j][0]
&& mouseXY[0] < (this.coords2[i][j][0] + this.coords2[i][j][2])
&& mouseXY[1] > this.coords2[i][j][1]
&& mouseXY[1] < (this.coords2[i][j][1] + this.coords2[i][j][3])
) {
indexes = [i, j];
break outer;
}
}
}
}
if (typeof values === 'number') {
values = [values];
}
@ -4325,6 +4485,261 @@ this.context.lineTo(
//
// Draw a dumbbell chart
//
this.drawdumbbell = function ()
{
var dumbbellCoords = [];
var obj = this;
var seq = 0;
//var y = obj.getYCoord(this.data[0]);
this.coords = [];
this.coords2 = [];
this.data.forEach(function (v, k, arr)
{
var section = ((obj.canvas.width - obj.properties.marginLeft - obj.properties.marginRight) / obj.data.length);
var coordX = (section * k) + obj.properties.marginLeft + (section / 2);
var coordW = obj.properties.variantDumbbellEndRadius;
if (obj.properties.shadow) {
RGraph.setShadow(
obj,
obj.properties.shadowColor,
obj.properties.shadowOffsetx,
obj.properties.shadowOffsety,
obj.properties.shadowBlur
);
}
//
// TODO Need to convert this if condition
//
if (v.length > 2) {
obj.coords2[k] = [];
for (var j=1; j<v.length; ++j) {
var coordY = obj.getYCoord(v[j]);
var coordH = obj.getYCoord(v[j - 1]) - obj.getYCoord(v[j]);
obj.path('b r % % % %',
coordX,
coordY,
coordW,
coordH//(coordH * 2) + (2 * obj.properties.shadowOffsety)
);
obj.pathDumbbell(
coordX,
coordY,
coordW,
coordH,
j === (v.length - 1) && (RGraph.isNull(obj.properties.variantDumbbellEndTop) || obj.properties.variantDumbbellEndTop),
j === 1 && (RGraph.isNull(obj.properties.variantDumbbellEndBottom) || obj.properties.variantDumbbellEndBottom)
);
// Add the rect to the canvas
if (obj.properties.colorsSequential) {
obj.path('f ' + obj.properties.colorsDumbbell[seq]);
} else {
obj.path('f ' + obj.properties.colorsDumbbell[j - 1]);
}
// Determine the height of the
// hotspot
var radius = Math.max(
(obj.properties.variantDumbbellEndTopRadius || obj.properties.variantDumbbellEndTopRadius || 0),
(obj.properties.variantDumbbellEndBottomRadius || obj.properties.variantDumbbellEndBottomRadius || 0)
);
radius = Math.max(coordW, radius);
//
// Calculate the shadowOffset so that the
// highlight covers the shadow as well.
//
var shadowOffset = Math.max(
Math.abs(obj.properties.shadowOffsetx),
Math.abs(obj.properties.shadowOffsety)
);
var coords = [
coordX - radius,
coordY - (j === (v.length - 1) ? radius : 0),
coordW + (2 * radius),
coordH + (j === 1 || (j === v.length - 1) ? radius : 0),
];
// Modify the coords so that the
// shadowOffset is taken into account when
// the highlight is added.
/*
// First segment
if (j === 1) {
// Horizontal offset manglement
if (obj.properties.shadowOffsetx < 0) {
coords[0] -= shadowOffset;
coords[2] += shadowOffset;
} else {
coords[2] += shadowOffset;
}
// Vertical offset manglement
if (obj.properties.shadowOffsety > 0) {
coords[3] += shadowOffset;
}
// Last segment
} else if (j === (v.length - 1) ) {
// Horizontal offset manglement
if (obj.properties.shadowOffsetx > 0) {
coords[2] += shadowOffset;
} else {
coords[0] -= shadowOffset;
coords[2] += shadowOffset;
}
// Vertical offset manglement
if (obj.properties.shadowOffsety > 0) {
//coords[3] += shadowOffset;
} else if (obj.properties.shadowOffsety < 0) {
coords[1] -= shadowOffset;
coords[3] += shadowOffset;
}
// Middle segments
} else {
// Vertical offset manglement
if (obj.properties.shadowOffsetx > 0) {
coords[2] += shadowOffset;
} else {
coords[0] -= shadowOffset;
coords[2] += shadowOffset;
}
}
*/
obj.coords.push(coords);
obj.coords2[k].push(coords);
seq++;
}
// //
// Need this so that the colors are
// used in the coorect order
//
seq--;
// Only TWO Y values - so a minimum and a
// maximum.
} else {
obj.coords2[k] = [];
var coordH = obj.getYCoord(v[0]) - obj.getYCoord(v[1]);
var coordY = obj.getYCoord(v[0]) - coordH;
obj.pathDumbbell(
coordX,
coordY,
coordW,
coordH
);
if (obj.properties.colorsSequential) {
obj.path('f ' + obj.properties.colorsDumbbell[k]);
} else {
obj.path('f ' + obj.properties.colorsDumbbell[0]);
}
// Store the dumbbell coordinates
var coords = [
coordX - obj.properties.variantDumbbellEndRadius - obj.properties.shadowOffsetx,
coordY - obj.properties.shadowOffsety - obj.properties.variantDumbbellEndRadius,
coordW + (2 * obj.properties.variantDumbbellEndRadius) + (2 * obj.properties.shadowOffsetx),
coordH + (2 * obj.properties.variantDumbbellEndRadius) + (2 * obj.properties.shadowOffsety)
];
obj.coords.push(coords);
obj.coords2[k].push(coords);
}
seq++;
RGraph.noShadow(obj);
});
};
//
// Paths a dumbbell bar
//
this.pathDumbbell = function (x, y, w, h, topEnd = true, bottomEnd = true)
{
this.path(
'b r % % % %',
x + (this.properties.variantDumbbellLinewidth / 2) - 2,
y,
this.properties.variantDumbbellLinewidth,
h
);
if (this.properties.variantDumbbellEndTop && topEnd) {
this.path(
'm % % a % % % 0 6.29 false',
x + (w/2), y,
x + (w/2), y, (RGraph.isNumber(this.properties.variantDumbbellEndTopRadius) ? this.properties.variantDumbbellEndTopRadius : this.properties.variantDumbbellEndRadius)
);
}
if (this.properties.variantDumbbellEndBottom && bottomEnd) {
this.path(
'm % % a % % % 0 6.29 false',
x + (w/2), y+h,
x + (w/2), y+h, (RGraph.isNumber(this.properties.variantDumbbellEndBottomRadius) ? this.properties.variantDumbbellEndBottomRadius : this.properties.variantDumbbellEndRadius)
);
}
};
//
// Register the object
//

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,16 @@
'version:2025-10-08 (7.01)';
'version:2026-08-11 (7.21)';
//
// o---------------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net/license.html |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
// | free to use and there are no restrictions on what you can use RGraph for! |
// | If the GPL license does not suit you however, then there's an inexpensive |
// | commercial license option available. See the URL above for more details. |
// o---------------------------------------------------------------------------------o
// o---------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. This means |
// | that it's free to use for any purpose. The GPL license does have |
// | consequences on the license of the software that you include it in, |
// | however. If this is not desirable, then there's an inexpensive commercial |
// | license option available. See the RGraph website for more details. |
// o---------------------------------------------------------------------------o
//
// Having this here means that the RGraph libraries can be included in any order, instead of you having
@ -93,7 +94,6 @@
width: null,
height: null,
halign: 'left',
valign: 'top',
@ -121,9 +121,12 @@
tooltipsPointerOffsetx: 0,
tooltipsPointerOffsety: 0,
tooltipsPositionStatic: true,
tooltipsOffsetx: 0,
tooltipsOffsety: 0,
highlightStroke: 'rgba(0,0,0,0)',
highlightStroke: 'transparent',
highlightFill: 'rgba(255,255,255,0.7)',
highlightFade: true,
colorsAlpha: 1,
@ -132,19 +135,20 @@
borderLinewidth: 1,
borderRadius: 0,
backgroundColor: 'rgba(0,0,0,0)',
backgroundColor: 'transparent',
text: null,
clearto: 'rgba(0,0,0,0)',
clearto: 'transparent',
clip: null,
events: {},
responsive: null,
scale: true,
scaleFactor: 2,
antialiasTranslate: false
antialiasTranslate: false,
style: []
};
@ -324,6 +328,18 @@
//
RGraph.fireCustomEvent(this, 'onbeforedraw');
//
// Add any CSS that has been specified to the document.
// This is general CSS and does not necessarily have to
// pertain to the canvas tag. It only gets added once
// to the document no matter how many times this draw
// function is called.
//
// Add the CSS to a <style> block in the <head>.
RGraph.addConfigurationBasedCSS(this);
var scaleFactor = RGraph.getScaleFactor(this);
@ -439,12 +455,13 @@
// Need this to stop a rectangle being drawn around
// the llast path that was added to the canvas.
this.context.beginPath();
//
// Draw a border around the image
//
/// !!!!!!
if (properties.border) {
this.context.strokeStyle = properties.borderColor;
@ -480,6 +497,7 @@
this.context.stroke();
if (borderRadius) {
this.context.save();
@ -722,33 +740,62 @@
//
// Each object type has its own Highlight() function which highlights the appropriate shape
// Each object type has its own Highlight() function
// which highlights the appropriate shape.
//
// @param object shape The shape to highlight
// @param object shape The shape to highlight.
//
this.highlight = function (shape)
{
if (properties.tooltipsHighlight) {
if (typeof properties.highlightStyle === 'function') {
(properties.highlightStyle)(shape);
} else {
this.path('b');
// If the highlightFade property is not set then call
// the highlight function multiple times when the
// globalAlpha is set at varying levels of transparency
// to fade the highlight in. If the variable is set,
// however, then this call is probably a part of said
// highlighting process so don't call ourselves
// again - just highlight the chart.
if (this.properties.highlightFade && !this.highlight.highlighting) {
this.roundedRect(
this.coords[0][0],
this.coords[0][1],
this.coords[0][2],
this.coords[0][3],
this.properties.borderRadius
// Add a variable to the highlight function (this
// function) to indicate that we're currently in
// the process of highlighting.
this.highlight.highlighting = true;
var obj = this;
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 20);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 40);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 60);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 80);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 100);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 120);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 140);
setTimeout(function() {obj.highlight.highlighting = false;}, 400);
return;
}
RGraph.clipTo.callback(this, function (obj)
{
if (typeof obj.properties.highlightStyle === 'function') {
(obj.properties.highlightStyle)(shape);
} else {
obj.path('b');
obj.roundedRect(
obj.coords[0][0],
obj.coords[0][1],
obj.coords[0][2],
obj.coords[0][3],
obj.properties.borderRadius
);
this.path(
obj.path(
'f % s %',
properties.highlightFill,
properties.highlightStroke
obj.properties.highlightFill,
obj.properties.highlightStroke
);
}
}
});// End of clipping callback.
};

View File

@ -1,15 +1,16 @@
'version:2025-10-08 (7.01)';
'version:2026-08-11 (7.21)';
//
// o---------------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net/license.html |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
// | free to use and there are no restrictions on what you can use RGraph for! |
// | If the GPL license does not suit you however, then there's an inexpensive |
// | commercial license option available. See the URL above for more details. |
// o---------------------------------------------------------------------------------o
// o---------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. This means |
// | that it's free to use for any purpose. The GPL license does have |
// | consequences on the license of the software that you include it in, |
// | however. If this is not desirable, then there's an inexpensive commercial |
// | license option available. See the RGraph website for more details. |
// o---------------------------------------------------------------------------o
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
@ -100,7 +101,6 @@
titleTopPos: null,
titleTopOffsetx: 0,
titleTopOffsety: 0,
titleTopSubtitle: null,
titleTopSubtitleFont: null,
titleTopSubtitleSize: null,
@ -129,27 +129,26 @@
scaleThousand: ',',
scaleUnitsPre: '',
scaleUnitsPost: '',
scalePoint: '.',
scaleThousand: ',',
labelsCount: 5,
labelsCentered: false,
labelsOffsetRadius: 0,
labelsOffsetAngle: 0,
labelsOffsetx: 0,
labelsOffsety: 0,
labelsSpecific: null,
labelsSpecificFormattedDecimals: 0,
labelsSpecificFormattedPoint: '.',
labelsSpecificFormattedThousand: ',',
labelsSpecificFormattedUnitsPre: '',
labelsSpecificFormattedUnitsPost: '',
labelsOffsetx: 0,
labelsOffsety: 0,
labelsFont: null,
labelsSize: null,
labelsColor: null,
labelsBold: null,
labelsItalic: null,
labelsValue: false,
labelsValue: false,
labelsValueYPos: 0.5,
labelsValueUnitsPre: '',
labelsValueUnitsPost: '',
@ -167,12 +166,12 @@
colorsRedStart: 0.9 * this.max,
colorsRedColor: '#DC3912',
colorsRedColor: '#dc3912',
colorsRedWidth: 5,
colorsYellowColor: '#FF9900',
colorsYellowColor: '#ff9900',
colorsYellowWidth: 5,
colorsGreenEnd: 0.7 * this.max,
colorsGreenColor: 'rgba(0,0,0,0)',
colorsGreenColor: 'transparent',
colorsGreenWidth: 5,
colorsRanges: null,
@ -187,8 +186,9 @@
borderOutline: 'black',
borderGradient: false,
centerpinColor: 'blue',
centerpinRadius: null,
centerpinColor: 'black',
centerpinGradient: false,
centerpinRadius: null,
tickmarksSmall: 25,
tickmarksSmallColor: 'black',
@ -203,19 +203,22 @@
annotatableLinewidth: 1,
annotatableColor: 'black',
shadow: true,
shadow: false,
shadowColor: 'gray',
shadowOffsetx: 0,
shadowOffsety: 0,
shadowBlur: 15,
clearto: 'rgba(0,0,0,0)',
events: {},
clearto: 'transparent',
events: {},
clip: null,
responsive: null,
scale: true,
scaleFactor: 2,
antialiasTranslate: false
antialiasTranslate: false,
style: []
};
@ -428,6 +431,18 @@
//
// Add any CSS that has been specified to the document.
// This is general CSS and does not necessarily have to
// pertain to the canvas tag. It only gets added once
// to the document no matter how many times this draw
// function is called.
//
// Add the CSS to a <style> block in the <head>.
RGraph.addConfigurationBasedCSS(this);
@ -933,16 +948,23 @@
var offset = (6 * scaleFactor);
var grad = this.context.createRadialGradient(
this.centerx + offset,
this.centery - offset,
0,
this.centerx + offset,
this.centery - offset,
(25 * scaleFactor)
);
grad.addColorStop(0, '#ddf');
grad.addColorStop(1, properties.centerpinColor);
//
// Gradient or not
//
if (this.properties.centerpinGradient) {
var grad = this.context.createRadialGradient(
this.centerx + offset,
this.centery - offset,
0,
this.centerx + offset,
this.centery - offset,
(25 * scaleFactor)
);
grad.addColorStop(0, '#ddf');
grad.addColorStop(1, this.properties.centerpinColor);
} else {
grad = this.properties.centerpinColor;
}
this.context.beginPath();
this.context.fillStyle = grad;
@ -997,11 +1019,7 @@
// If the labelsSpecific option is a string then turn it
// into an array.
if (typeof properties.labelsSpecific === 'string' ) {
properties.labelsSpecific = RGraph.arrayPad({
array: [],
length: properties.labelsCount,
value: properties.labelsSpecific
});
properties.labelsSpecific = RGraph.arrayPad([], properties.labelsCount, properties.labelsSpecific);
}
@ -1090,11 +1108,7 @@
valign: vAlign,
tag: properties.labelsSpecific ? 'labels.specific' : 'labels',
cssClass: properties.labelsSpecific
? RGraph.getLabelsCSSClassName({
object: this,
name: 'labelsClass',
index: i
})
? RGraph.getLabelsCSSClassName(this, 'labelsClass', i)
: ''
});
}
@ -1207,13 +1221,13 @@
// Move the Y coord up if there's a subtitle
if (typeof properties.titleTopSubtitle === 'string' || typeof properties.titleTopSubtitle === 'number') {
var titleTopSubtitleDim = RGraph.measureText({
bold: properties.titleTopSubtitleBold,
italic: properties.titleTopSubtitleItalic,
size: properties.titleTopSubtitleSize,
font: properties.titleTopSubtitleFont,
text: 'Mg'
});
var titleTopSubtitleDim = RGraph.measureText(
'Mg',
properties.titleTopSubtitleItalic,
properties.titleTopSubtitleBold,
properties.titleTopSubtitleFont,
properties.titleTopSubtitleSize
);
y -= titleTopSubtitleDim[1];
}
@ -1906,7 +1920,7 @@
var obj = this,
opt = arguments[0] ? arguments[0] : {},
callback = arguments[1] ? arguments[1] : function () {},
frames = opt.frames || 30,
frames = opt.frames || 60,
frame = 0;
// Don't want any strings

View File

@ -1,15 +1,16 @@
'version:2025-10-08 (7.01)';
'version:2026-08-11 (7.21)';
//
// o---------------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net/license.html |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
// | free to use and there are no restrictions on what you can use RGraph for! |
// | If the GPL license does not suit you however, then there's an inexpensive |
// | commercial license option available. See the URL above for more details. |
// o---------------------------------------------------------------------------------o
// o---------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. This means |
// | that it's free to use for any purpose. The GPL license does have |
// | consequences on the license of the software that you include it in, |
// | however. If this is not desirable, then there's an inexpensive commercial |
// | license option available. See the RGraph website for more details. |
// o---------------------------------------------------------------------------o
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
@ -49,13 +50,14 @@
this.properties =
{
backgroundBorder: 'black',
backgroundColor: '#eee',
backgroundColor: 'white',
backgroundLinesColor: '#ddd',
centerx: null,
centery: null,
radius: null,
labels: null,
labelsMargin: 35,
labelsFont: null,
labelsSize: null,
@ -81,7 +83,7 @@
needleLength: null,
needleWidth: 2,
needleHead: true,
needleTail: true,
needleTail: false,
needleType: 'pointer',
needleTriangleBorder: '#aaa',
@ -96,10 +98,10 @@
text: null,
colorsGreenMax: max * 0.75,
colorsGreenColor: '#0c0',
colorsYellowColor: '#cc0',
colorsGreenColor: '#00cc0088',
colorsYellowColor: '#ffff0088',
colorsRedMin: max * 0.9,
colorsRedColor: '#c00',
colorsRedColor: '#ff000088',
marginLeft: 35,
marginRight: 35,
@ -144,6 +146,7 @@
annotatable: false,
annotatableColor: 'black',
annotatableLinewidth: 1,
scaleDecimals: 0,
scalePoint: '.',
@ -152,7 +155,7 @@
scaleUnitsPost: '',
scaleZerostart: false,
border: true,
border: false,
borderColor1: '#BEBCB0',
borderColor2: '#F0EFEA',
borderColor3: '#BEBCB0',
@ -161,8 +164,6 @@
tickmarksHighlighted: true,
tickmarksLargeColor: '#999',
labels: null,
key: null,
keyBackground: 'white',
keyPosition: 'graph',
@ -196,13 +197,16 @@
adjustable: false,
clearto: 'rgba(0,0,0,0)',
clearto: 'transparent',
events: {},
clip: null,
responsive: null,
scale: true,
scaleFactor: 2,
antialiasTranslate: false
antialiasTranslate: false,
style: []
};
@ -385,6 +389,18 @@
//
// Add any CSS that has been specified to the document.
// This is general CSS and does not necessarily have to
// pertain to the canvas tag. It only gets added once
// to the document no matter how many times this draw
// function is called.
//
// Add the CSS to a <style> block in the <head>.
RGraph.addConfigurationBasedCSS(this);
// Translate half a pixel for antialiasing purposes - but
// only if it hasn't been done already
//
@ -1593,7 +1609,7 @@
var obj = this;
var opt = arguments[0] || {};
var frames = opt.frames || 30;
var frames = opt.frames || 60;
var frame = 0;
var current = this.currentValue || 0;
var origValue = Number(obj.currentValue);

View File

@ -1,15 +1,16 @@
'version:2025-10-08 (7.01)';
'version:2026-08-11 (7.21)';
//
// o---------------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net/license.html |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
// | free to use and there are no restrictions on what you can use RGraph for! |
// | If the GPL license does not suit you however, then there's an inexpensive |
// | commercial license option available. See the URL above for more details. |
// o---------------------------------------------------------------------------------o
// o---------------------------------------------------------------------------o
// | This file is part of the RGraph package - you can learn more at: |
// | |
// | https://www.rgraph.net |
// | |
// | RGraph is dual-licensed under the Open Source GPL license. This means |
// | that it's free to use for any purpose. The GPL license does have |
// | consequences on the license of the software that you include it in, |
// | however. If this is not desirable, then there's an inexpensive commercial |
// | license option available. See the RGraph website for more details. |
// o---------------------------------------------------------------------------o
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
@ -47,8 +48,8 @@
backgroundColor: 'white',
colorsStroke: 'black',
colors: ['red'],
colorsStroke: '#666',
colors: RGraph.getColors(),
marginLeft: 35,
marginRight: 35,
@ -56,7 +57,7 @@
marginBottom: 35,
tickmarksSize: 2,
tickmarksCount: 10,
tickmarksCount: 0,
textColor: 'black',
textFont: 'Arial, Verdana, sans-serif',
@ -102,15 +103,12 @@
titleSideOffsetx: 0,
titleSideOffsety: 0,
shadow: true,
shadow: false,
shadowOffsetx: 0,
shadowOffsety: 0,
shadowBlur: 15,
shadowColor: '#ddd',
resizable: false,
resizableHandleBackground: null,
contextmenu: null,
adjustable: false,
@ -172,19 +170,23 @@
tooltipsPositionStatic: true,
tooltipsHotspotIgnore: null,
highlightStroke: 'rgba(0,0,0,0)',
highlightStroke: 'transparent',
highlightFill: 'rgba(255,255,255,0.7)',
highlightFade: true,
clearto: 'rgba(0,0,0,0)',
clearto: 'transparent',
bulbBottomRadiusAdjust: 0,
bulbBottomRadius: null,
events: {},
clip: null,
responsive: null,
scale: true,
scaleFactor: 2,
antialiasTranslate: false
antialiasTranslate: false,
style: []
};
@ -407,6 +409,18 @@
//
// Add any CSS that has been specified to the document.
// This is general CSS and does not necessarily have to
// pertain to the canvas tag. It only gets added once
// to the document no matter how many times this draw
// function is called.
//
// Add the CSS to a <style> block in the <head>.
RGraph.addConfigurationBasedCSS(this);
// Translate half a pixel for antialiasing purposes - but
// only if it hasn't been done already
//
@ -1124,20 +1138,50 @@
//
this.highlight = function (shape)
{
if (properties.tooltipsHighlight) {
// If the highlightFade property is not set then call
// the highlight function multiple times when the
// globalAlpha is set at varying levels of transparency
// to fade the highlight in. If the variable is set,
// however, then this call is probably a part of said
// highlighting process so don't call ourselves
// again - just highlight the chart.
if (this.properties.highlightFade && !this.highlight.highlighting) {
if (typeof properties.highlightStyle === 'function') {
(properties.highlightStyle)(shape);
return;
}
// Add a variable to the highlight function (this
// function) to indicate that we're currently in
// the process of highlighting.
this.highlight.highlighting = true;
this.pathBar();
var obj = this;
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 20);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 40);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 60);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 80);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 100);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 120);
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 140);
setTimeout(function() {obj.highlight.highlighting = false;}, 400);
this.path(
's % f %',
properties.highlightStroke, properties.highlightFill
);
return;
}
RGraph.clipTo.callback(this, function (obj)
{
if (obj.properties.tooltipsHighlight) {
if (typeof obj.properties.highlightStyle === 'function') {
(obj.properties.highlightStyle)(shape);
return;
}
obj.pathBar();
obj.path(
's % f %',
obj.properties.highlightStroke, obj.properties.highlightFill
);
}
});
};

View File

@ -70,8 +70,6 @@
</span>
</nav>
<section id="estado-estacion" class="estado-estacion" aria-label="Estado de la estación"></section>
<br><br>
<div id="superior" class="container">
<div class="row">
<div class="col-2" align="center" style="vertical-align:top;">

View File

@ -1,5 +1,12 @@
27/09/2026 23:00:15 - 1|PURGADO|Archivo de Debug
27/09/2026 23:00:44 - 0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.
27/09/2026 23:01:01 - 0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.
27/09/2026 23:01:10 - 0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.
27/09/2026 23:01:42 - 0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.
27/09/2026 23:13:40 - 1|PURGADO|Archivo de Debug
27/09/2026 23:13:41 - 1|PURGADO|Archivo de Pendientes
27/09/2026 23:18:43 - 0|CORE|🕵️. Buscando Modulo USB para el S.O - linux_x64_gui
27/09/2026 23:18:43 - 0|CORE|✅ Modulo node-hid cargado correctamente.
27/09/2026 23:18:43 - 0|CORE|⏳ Iniciando Ema Libre en Modo gráfico o Web.
27/09/2026 23:20:26 - 0|CORE|🕵️. Buscando Modulo USB para el S.O - linux_x64_gui
27/09/2026 23:20:26 - 0|CORE|✅ Modulo node-hid cargado correctamente.
27/09/2026 23:20:26 - 0|CORE|⏳ Iniciando Ema Libre en Modo gráfico o Web.
27/09/2026 23:21:09 - 0|CORE|🕵️. Buscando Modulo USB para el S.O - linux_x64_gui
27/09/2026 23:21:09 - 0|CORE|✅ Modulo node-hid cargado correctamente.
27/09/2026 23:21:09 - 0|CORE|⏳ Iniciando Ema Libre en Modo gráfico o Web.
27/09/2026 23:23:30 - 0|CORE|🔚 SALIR: Se cerro el core de EMA LIBRE. Hasta luego!!!.