major rework
- modified chartjs for better zoom on touchpad - flexible number of charts - handle bool as checkbox - handle enum as select (pull down menu) - disable swiper where not needed and many more
This commit is contained in:
1 parent
1de819cd26
commit
97c6aa1a87
14 files changed
+2480
-1609
No files matched your search
@@ -21,7 +21,7 @@
|
||||
<!-- JS-Files -->
|
||||
<script src="externalFiles/alertify.js"></script>
|
||||
<script src="externalFiles/eventsource.js"></script>
|
||||
<script src="externalFiles/d3.min.js"></script>
|
||||
<!-- <script src="externalFiles/d3.min.js"></script> -->
|
||||
<script src="externalFiles/swiper.min.js"></script>
|
||||
<script src="externalFiles/Chart.bundle.min.js"></script>
|
||||
<script src="externalFiles/hammer.js"></script>
|
||||
@@ -30,7 +30,7 @@
|
||||
<script src="jsFiles/SEAWebClientSwiper.js"></script>
|
||||
<script src="jsFiles/SEAWebClientGroup.js"></script>
|
||||
<script src="jsFiles/SEAWebClientConsole.js"></script>
|
||||
<script src="jsFiles/SEAWebClientGraph.js"></script>
|
||||
<script src="jsFiles/SEAWebClientGraphics.js"></script>
|
||||
<script src="jsFiles/SEAWebClientCommunication.js"></script>
|
||||
<script src="jsFiles/SEAWebClientMain.js"></script>
|
||||
</head>
|
||||
|
||||
@@ -87,7 +87,9 @@
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
position: absolute;
|
||||
background-color: rgb(255,255,255,0.8);
|
||||
/* background-color: rgb(255,255,255,0.7); */
|
||||
background-color: white;
|
||||
opacity: 0.7;
|
||||
color: #000000;
|
||||
padding: 0.3em;
|
||||
/*transition: left 0.5s, top 0.5s;*/
|
||||
@@ -96,22 +98,39 @@
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
cursor: grab;
|
||||
border: 1px solid black;
|
||||
border: 1px solid #777777;
|
||||
}
|
||||
|
||||
.legend:active{
|
||||
cursor: grabbing;
|
||||
}
|
||||
.legend:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.legendanchor {
|
||||
border: solid black;
|
||||
border-width: 0 1px 1px 0;
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 7px;
|
||||
transform: rotate(-45deg) translate(-7px, -3px);
|
||||
-webkit-transform: rotate(-45deg) translateX(-7px, -3px);
|
||||
}
|
||||
|
||||
|
||||
body.black .legend{
|
||||
background-color: rgb(0,0,0,0.8);
|
||||
/*background-color: rgb(0,0,0,0.8);*/
|
||||
background-color: black;
|
||||
opacity: 0.7;
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.legend .controls{
|
||||
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.legend .control{
|
||||
@@ -119,32 +138,53 @@ body.black .legend{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/*
|
||||
.legend .vcontrol{
|
||||
clear: both;
|
||||
float: left;
|
||||
border-bottom: 1px solid black;
|
||||
padding-bottom: 0.1em;
|
||||
padding-top: 0.1em;
|
||||
}
|
||||
*/
|
||||
|
||||
.legend .subcontrol{
|
||||
.legend .spacer {
|
||||
width: 0.5em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hidebox{
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding-bottom: 0.1em;
|
||||
padding-top: 0.1em;
|
||||
color: #777777;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.legend .subcontrol:hover{
|
||||
color: #000000;
|
||||
.dselect{
|
||||
/*display: flex; */
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
background-color: #dddddd;
|
||||
padding: 2px;
|
||||
/*z-index: 10; */
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
}
|
||||
|
||||
.legend .subspacer{
|
||||
display: inline-block;
|
||||
width: 0.2em;
|
||||
.dselect:hover{
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.legend .vcontrol:hover{
|
||||
.cursorline{
|
||||
display: none;
|
||||
background-color: black;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 100px;
|
||||
width: 2px;
|
||||
height: 1000px;
|
||||
}
|
||||
|
||||
.legend .control:hover{
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
@@ -153,33 +193,32 @@ body.black .legend{
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.legendel{
|
||||
.legendrow{
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.legendel:hover{
|
||||
.legendrow:hover{
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.legendel .color{
|
||||
.legendrow .colorline{
|
||||
width: 2em;
|
||||
height: 0.1em;
|
||||
margin-top: 0.45em;
|
||||
height: 2px;
|
||||
margin-bootom: 0.45em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.legendel .value{
|
||||
.value{
|
||||
margin-left: 1em;
|
||||
min-width: 3em
|
||||
}
|
||||
|
||||
.legendel.hidden .value{
|
||||
/*
|
||||
.legendrow.hidden .value{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*.legendel.hidden:before{
|
||||
.legendel.hidden:before{
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 0.05em;
|
||||
@@ -187,12 +226,13 @@ body.black .legend{
|
||||
margin-top: -0.025em;
|
||||
background-color: #FFF;
|
||||
position: absolute;
|
||||
}*/
|
||||
}
|
||||
|
||||
.legendel.hidden{
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.legendel.hidden .color{
|
||||
.legendel.hidden .colorline{
|
||||
opacity: 0;
|
||||
}
|
||||
*/
|
||||
@@ -14,6 +14,10 @@
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.swiper-button-prev.swiper-button-disabled,
|
||||
.swiper-button-next.swiper-button-disabled {
|
||||
opacity: 0;
|
||||
}
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* PANEL */
|
||||
.panel {
|
||||
|
||||
@@ -1,20 +1,685 @@
|
||||
/*!
|
||||
* @license
|
||||
* chartjs-plugin-zoom
|
||||
* http://chartjs.org/
|
||||
* Version: 0.7.3
|
||||
*
|
||||
* Copyright 2019 Chart.js Contributors
|
||||
* Released under the MIT license
|
||||
* https://github.com/chartjs/chartjs-plugin-zoom/blob/master/LICENSE.md
|
||||
//'use strict';
|
||||
|
||||
/*
|
||||
import {Chart} from 'chart.js';
|
||||
import Hammer from 'hammerjs';
|
||||
*/
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
// Take the zoom namespace of Chart
|
||||
var zoomNS = Chart.Zoom = Chart.Zoom || {};
|
||||
|
||||
// Where we store functions to handle different scale types
|
||||
var zoomFunctions = zoomNS.zoomFunctions = zoomNS.zoomFunctions || {};
|
||||
var panFunctions = zoomNS.panFunctions = zoomNS.panFunctions || {};
|
||||
|
||||
function resolveOptions(chart, options) {
|
||||
var deprecatedOptions = {};
|
||||
if (typeof chart.options.pan !== 'undefined') {
|
||||
deprecatedOptions.pan = chart.options.pan;
|
||||
}
|
||||
if (typeof chart.options.zoom !== 'undefined') {
|
||||
deprecatedOptions.zoom = chart.options.zoom;
|
||||
}
|
||||
var props = chart.$zoom;
|
||||
options = props._options = helpers.merge({}, [options, deprecatedOptions]);
|
||||
|
||||
// Install listeners. Do this dynamically based on options so that we can turn zoom on and off
|
||||
// We also want to make sure listeners aren't always on. E.g. if you're scrolling down a page
|
||||
// and the mouse goes over a chart you don't want it intercepted unless the plugin is enabled
|
||||
var node = props._node;
|
||||
var zoomEnabled = options.zoom && options.zoom.enabled;
|
||||
var dragEnabled = options.zoom.drag;
|
||||
if (zoomEnabled && !dragEnabled) {
|
||||
node.addEventListener('wheel', props._wheelHandler);
|
||||
} else {
|
||||
node.removeEventListener('wheel', props._wheelHandler);
|
||||
}
|
||||
if (zoomEnabled && dragEnabled) {
|
||||
node.addEventListener('mousedown', props._mouseDownHandler);
|
||||
node.ownerDocument.addEventListener('mouseup', props._mouseUpHandler);
|
||||
} else {
|
||||
node.removeEventListener('mousedown', props._mouseDownHandler);
|
||||
node.removeEventListener('mousemove', props._mouseMoveHandler);
|
||||
node.ownerDocument.removeEventListener('mouseup', props._mouseUpHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function storeOriginalOptions(chart) {
|
||||
var originalOptions = chart.$zoom._originalOptions;
|
||||
helpers.each(chart.scales, function(scale) {
|
||||
if (!originalOptions[scale.id]) {
|
||||
originalOptions[scale.id] = helpers.clone(scale.options);
|
||||
}
|
||||
});
|
||||
helpers.each(originalOptions, function(opt, key) {
|
||||
if (!chart.scales[key]) {
|
||||
delete originalOptions[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} mode can be 'x', 'y' or 'xy'
|
||||
* @param {string} dir can be 'x' or 'y'
|
||||
* @param {Chart} chart instance of the chart in question
|
||||
*/
|
||||
!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o(require("chart.js"),require("hammerjs")):"function"==typeof define&&define.amd?define(["chart.js","hammerjs"],o):(e=e||self).ChartZoom=o(e.Chart,e.Hammer)}(this,function(e,o){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e,o=o&&o.hasOwnProperty("default")?o.default:o;var n=e.helpers,t=e.Zoom=e.Zoom||{},a=t.zoomFunctions=t.zoomFunctions||{},i=t.panFunctions=t.panFunctions||{};function m(e,o){var t={};void 0!==e.options.pan&&(t.pan=e.options.pan),void 0!==e.options.pan&&(t.zoom=e.options.zoom);var a=e.$zoom;o=a._options=n.merge({},[o,t]);var i=a._node,m=o.zoom&&o.zoom.enabled,r=o.zoom.drag;m&&!r?i.addEventListener("wheel",a._wheelHandler):i.removeEventListener("wheel",a._wheelHandler),m&&r?(i.addEventListener("mousedown",a._mouseDownHandler),i.ownerDocument.addEventListener("mouseup",a._mouseUpHandler)):(i.removeEventListener("mousedown",a._mouseDownHandler),i.removeEventListener("mousemove",a._mouseMoveHandler),i.ownerDocument.removeEventListener("mouseup",a._mouseUpHandler))}function r(e){var o=e.$zoom._originalOptions;n.each(e.scales,function(e){o[e.id]||(o[e.id]=n.clone(e.options))}),n.each(o,function(n,t){e.scales[t]||delete o[t]})}function l(e,o){return void 0===e||"string"==typeof e&&-1!==e.indexOf(o)}function s(e,o){if(e.scaleAxes&&e.rangeMax&&!n.isNullOrUndef(e.rangeMax[e.scaleAxes])){var t=e.rangeMax[e.scaleAxes];o>t&&(o=t)}return o}function c(e,o){if(e.scaleAxes&&e.rangeMin&&!n.isNullOrUndef(e.rangeMin[e.scaleAxes])){var t=e.rangeMin[e.scaleAxes];o<t&&(o=t)}return o}function u(e,o,n,t){var a=e.max-e.min,i=a*(o-1),m=e.isHorizontal()?n.x:n.y,r=(e.getValueForPixel(m)-e.min)/a,l=i*r,u=i*(1-r);e.options.ticks.min=c(t,e.min+l),e.options.ticks.max=s(t,e.max-u)}function d(e,o,n,t){var i=a[e.type];i&&i(e,o,n,t)}function p(e,o,t,a,i){var m=e.chartArea;a||(a={x:(m.left+m.right)/2,y:(m.top+m.bottom)/2});var s=e.$zoom._options.zoom;if(s.enabled){r(e);var c,u=s.mode;c="xy"===u&&void 0!==i?i:"xy",n.each(e.scales,function(e){e.isHorizontal()&&l(u,"x")&&l(c,"x")?(s.scaleAxes="x",d(e,o,a,s)):!e.isHorizontal()&&l(u,"y")&&l(c,"y")&&(s.scaleAxes="y",d(e,t,a,s))}),e.update(0),"function"==typeof s.onZoom&&s.onZoom({chart:e})}}function v(e,o,t){var a,i=e.options.ticks,m=e.min,r=e.max,l=e.getValueForPixel(e.getPixelForValue(m)-o),s=e.getValueForPixel(e.getPixelForValue(r)-o),c=l=l.valueOf?l.valueOf():l,u=s=s.valueOf?s.valueOf():s;t.scaleAxes&&t.rangeMin&&!n.isNullOrUndef(t.rangeMin[t.scaleAxes])&&(c=t.rangeMin[t.scaleAxes]),t.scaleAxes&&t.rangeMax&&!n.isNullOrUndef(t.rangeMax[t.scaleAxes])&&(u=t.rangeMax[t.scaleAxes]),l>=c&&s<=u?(i.min=l,i.max=s):l<c?(a=m-c,i.min=c,i.max=r-a):s>u&&(a=u-r,i.max=u,i.min=m+a)}function f(e,o,n){var t=i[e.type];t&&t(e,o,n)}e.Zoom.defaults=e.defaults.global.plugins.zoom={pan:{enabled:!1,mode:"xy",speed:20,threshold:10},zoom:{enabled:!1,mode:"xy",sensitivity:3,speed:.1}},t.zoomFunctions.category=function(e,o,n,a){var i=e.chart.data.labels,m=e.minIndex,r=i.length-1,l=e.maxIndex,u=a.sensitivity,d=e.isHorizontal()?e.left+e.width/2:e.top+e.height/2,p=e.isHorizontal()?n.x:n.y;t.zoomCumulativeDelta=o>1?t.zoomCumulativeDelta+1:t.zoomCumulativeDelta-1,Math.abs(t.zoomCumulativeDelta)>u&&(t.zoomCumulativeDelta<0?(p>=d?m<=0?l=Math.min(r,l+1):m=Math.max(0,m-1):p<d&&(l>=r?m=Math.max(0,m-1):l=Math.min(r,l+1)),t.zoomCumulativeDelta=0):t.zoomCumulativeDelta>0&&(p>=d?m=m<l?m=Math.min(l,m+1):m:p<d&&(l=l>m?l=Math.max(m,l-1):l),t.zoomCumulativeDelta=0),e.options.ticks.min=c(a,i[m]),e.options.ticks.max=s(a,i[l]))},t.zoomFunctions.time=function(e,o,n,t){u(e,o,n,t),e.options.ticks.min=e.options.ticks.min,e.options.ticks.max=e.options.ticks.max},t.zoomFunctions.linear=u,t.zoomFunctions.logarithmic=u,t.panFunctions.category=function(e,o,n){var a,i=e.chart.data.labels,m=i.length-1,r=Math.max(e.ticks.length,1),l=n.speed,u=e.minIndex,d=Math.round(e.width/(r*l));t.panCumulativeDelta+=o,u=t.panCumulativeDelta>d?Math.max(0,u-1):t.panCumulativeDelta<-d?Math.min(m-r+1,u+1):u,t.panCumulativeDelta=u!==e.minIndex?0:t.panCumulativeDelta,a=Math.min(m,u+r-1),e.options.ticks.min=c(n,i[u]),e.options.ticks.max=s(n,i[a])},t.panFunctions.time=function(e,o,n){v(e,o,n);var t=e.options;t.ticks.min=t.ticks.min,t.ticks.max=t.ticks.max},t.panFunctions.linear=v,t.panFunctions.logarithmic=v,t.panCumulativeDelta=0,t.zoomCumulativeDelta=0;var h={id:"zoom",afterInit:function(e){e.resetZoom=function(){r(e);var o=e.$zoom._originalOptions;n.each(e.scales,function(e){var n=e.options.time,t=e.options.ticks;o[e.id]?(n&&(n.min=o[e.id].ticks.min,n.max=o[e.id].ticks.max),t&&(t.min=o[e.id].ticks.min,t.max=o[e.id].ticks.max)):(n&&(delete n.min,delete n.max),t&&(delete t.min,delete t.max))}),e.update()}},beforeUpdate:function(e,o){m(e,o)},beforeInit:function(e,a){e.$zoom={_originalOptions:{}};var i=e.$zoom._node=e.chart.ctx.canvas;m(e,a);var s=e.$zoom._options,c=s.pan&&s.pan.threshold;e.$zoom._mouseDownHandler=function(o){i.addEventListener("mousemove",e.$zoom._mouseMLine truncated
|
||||
if(e.$zoom._wheelHandler=function(o){/*if(!o.ctrlKey){return;}*/
|
||||
//o.stopImmediatePropagation();
|
||||
var n=o.target.getBoundingClientRect(),
|
||||
t={x:o.clientX-n.left,y:o.clientY-n.top},
|
||||
a=e.$zoom._options.zoom,
|
||||
i=a.speed;
|
||||
o.deltaY>=0&&(i=-i),p(e,1+i,1+i,t),clearTimeout(u),u=setTimeout(function(){"function"==typeof a.onZoomComplete&&a.onZoomComplete({chart:e})},250),
|
||||
o.cancelable&&o.preventDefault()},o)
|
||||
{var d,v=new o.Manager(i);v.add(new o.Pinch),v.add(new o.Pan({threshold:c}));var h=function(o){var n=1/d*o.scale,t=o.target.getBoundingClientRect(),a={x:o.center.x-t.left,y:o.center.y-t.top},i=Math.abs(o.pointers[0].clientX-o.pointers[1].clientX),m=Math.abs(o.pointers[0].clientY-o.pointers[1].clientY),r=i/m;p(e,n,n,a,r>.3&&r<1.7?"xy":i>m?"x":"y"),d=o.scale};v.on("pinchstart",function(){d=1}),v.on("pinch",h),v.on("pinchend",function(e){h(e),d=null,t.zoomCumulativeDelta=0});var x=null,g=null,z=!1,_=function(o){if(null!==x&&null!==g){z=!0;var t=o.deltaX-x,a=o.deltaY-g;x=o.deltaX,g=o.deltaY,function(e,o,t){r(e);var a=e.$zoom._options.pan;if(a.enabled){var i=a.mode;n.each(e.scales,function(e){e.isHorizontal()&&l(i,"x")&&0!==o?(a.scaleAxes="x",f(e,o,a)):!e.isHorizontal()&&l(i,"y")&&0!==t&&(a.scaleAxes="y",f(e,t,a))}),e.update(0),"function"==typeof a.onPan&&a.onPan({chart:e})}}(e,t,a)}};v.on("panstart",function(e){x=0,g=0,_(e)}),v.on("panmove",_),v.on("panend",function(){x=null,g=null,t.panCumulativeDelta=0,setTimeout(function(){z=!1},500);var o=e.$zoom._options.pan;"function"==typeof o.onPanComplete&&o.onPanComplete({chart:e})}),e.$zoom._ghostClickHandler=function(e){z&&e.cancelable&&(e.stopImmediatePropagation(),e.preventDefault())},i.addEventListener("click",e.$zoom._ghostClickHandler),e._mc=v}},beforeDatasetsDraw:function(e){var o=e.chart.ctx;if(e.$zoom._dragZoomEnd){var n=function(e){for(var o=e.scales,n=Object.keys(o),t=0;t<n.length;t++){var a=o[n[t]];if(a.isHorizontal())return a}}(e),t=function(e){for(var o=e.scales,n=Object.keys(o),t=0;t<n.length;t++){var a=o[n[t]];if(!a.isHorizontal())return a}}(e),a=e.$zoom._dragZoomStart,i=e.$zoom._dragZoomEnd,m=n.left,r=n.right,s=t.top,c=t.bottom;if(l(e.$zoom._options.zoom.mode,"x")){var u=a.target.getBoundingClientRect().left;m=Math.min(a.clientX,i.clientX)-u,r=Math.max(a.clientX,i.clientX)-u}if(l(e.$zoom._options.zoom.mode,"y")){var d=a.target.getBoundingClientRect().top;s=Math.min(a.clientY,i.clientY)-d,c=Math.max(a.clientY,i.clientY)-d}var p=r-m,v=c-s,f=e.$zoom._options.zoom.drag;o.save(),o.beginPath(),o.fillStyle=f.backgroundColor||"rgba(225,225,225,0.3)",o.fillRect(m,s,p,v),f.borderWidth>0&&(o.lineWidth=f.borderWidth,o.strokeStyle=f.borderColor||"rgba(225,225,225)",o.strokeRect(m,s,p,v)),o.restore()}},destroy:function(e){if(e.$zoom){var o=e.$zoom,n=o._node;n.removeEventListener("mousedown",o._mouseDownHandler),n.removeEventListener("mousemove",o._mouseMoveHandler),n.ownerDocument.removeEventListener("mouseup",o._mouseUpHandler),n.removeEventListener("wheel",o._wheelHandler),n.removeEventListener("click",o._ghostClickHandler),delete e.$zoom;var t=e._mc;t&&(t.remove("pinchstart"),t.remove("pinch"),t.remove("pinchend"),t.remove("panstart"),t.remove("pan"),t.remove("panend"))}}};return e.plugins.register(h),h});
|
||||
function directionEnabled(mode, dir, chart) {
|
||||
if (mode === undefined) {
|
||||
return true;
|
||||
} else if (typeof mode === 'string') {
|
||||
return mode.indexOf(dir) !== -1;
|
||||
} else if (typeof mode === 'function') {
|
||||
return mode({chart: chart}).indexOf(dir) !== -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function rangeMaxLimiter(zoomPanOptions, newMax) {
|
||||
if (zoomPanOptions.scaleAxes && zoomPanOptions.rangeMax &&
|
||||
!helpers.isNullOrUndef(zoomPanOptions.rangeMax[zoomPanOptions.scaleAxes])) {
|
||||
var rangeMax = zoomPanOptions.rangeMax[zoomPanOptions.scaleAxes];
|
||||
if (newMax > rangeMax) {
|
||||
newMax = rangeMax;
|
||||
}
|
||||
}
|
||||
return newMax;
|
||||
}
|
||||
|
||||
function rangeMinLimiter(zoomPanOptions, newMin) {
|
||||
if (zoomPanOptions.scaleAxes && zoomPanOptions.rangeMin &&
|
||||
!helpers.isNullOrUndef(zoomPanOptions.rangeMin[zoomPanOptions.scaleAxes])) {
|
||||
var rangeMin = zoomPanOptions.rangeMin[zoomPanOptions.scaleAxes];
|
||||
if (newMin < rangeMin) {
|
||||
newMin = rangeMin;
|
||||
}
|
||||
}
|
||||
return newMin;
|
||||
}
|
||||
|
||||
function zoomCategoryScale(scale, zoom, center, zoomOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var minIndex = scale.min;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var maxIndex = scale.max;
|
||||
var sensitivity = zoomOptions.sensitivity;
|
||||
var chartCenter = scale.isHorizontal() ? scale.left + (scale.width / 2) : scale.top + (scale.height / 2);
|
||||
var centerPointer = scale.isHorizontal() ? center.x : center.y;
|
||||
|
||||
zoomNS.zoomCumulativeDelta = zoom > 1 ? zoomNS.zoomCumulativeDelta + 1 : zoomNS.zoomCumulativeDelta - 1;
|
||||
|
||||
if (Math.abs(zoomNS.zoomCumulativeDelta) > sensitivity) {
|
||||
if (zoomNS.zoomCumulativeDelta < 0) {
|
||||
if (centerPointer >= chartCenter) {
|
||||
if (minIndex <= 0) {
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
} else {
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
}
|
||||
} else if (centerPointer < chartCenter) {
|
||||
if (maxIndex >= lastLabelIndex) {
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
} else {
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
}
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
} else if (zoomNS.zoomCumulativeDelta > 0) {
|
||||
if (centerPointer >= chartCenter) {
|
||||
minIndex = minIndex < maxIndex ? minIndex = Math.min(maxIndex, minIndex + 1) : minIndex;
|
||||
} else if (centerPointer < chartCenter) {
|
||||
maxIndex = maxIndex > minIndex ? maxIndex = Math.max(minIndex, maxIndex - 1) : maxIndex;
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
}
|
||||
scale.options.min = rangeMinLimiter(zoomOptions, labels[minIndex]);
|
||||
scale.options.max = rangeMaxLimiter(zoomOptions, labels[maxIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
function zoomNumericalScale(scale, zoom, center, zoomOptions) {
|
||||
var range = scale.max - scale.min;
|
||||
var newDiff = range * (zoom - 1);
|
||||
|
||||
var centerPoint = scale.isHorizontal() ? center.x : center.y;
|
||||
var minPercent = (scale.getValueForPixel(centerPoint) - scale.min) / range;
|
||||
var maxPercent = 1 - minPercent;
|
||||
|
||||
var minDelta = newDiff * minPercent;
|
||||
var maxDelta = newDiff * maxPercent;
|
||||
|
||||
scale.options.ticks.min = rangeMinLimiter(zoomOptions, scale.min + minDelta);
|
||||
scale.options.ticks.max = rangeMaxLimiter(zoomOptions, scale.max - maxDelta);
|
||||
//console.log("ZOOM", zoom, scale)
|
||||
}
|
||||
|
||||
function zoomScale(scale, zoom, center, zoomOptions) {
|
||||
var fn = zoomFunctions[scale.type];
|
||||
if (fn) {
|
||||
fn(scale, zoom, center, zoomOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param chart The chart instance
|
||||
* @param {number} percentZoomX The zoom percentage in the x direction
|
||||
* @param {number} percentZoomY The zoom percentage in the y direction
|
||||
* @param {{x: number, y: number}} focalPoint The x and y coordinates of zoom focal point. The point which doesn't change while zooming. E.g. the location of the mouse cursor when "drag: false"
|
||||
* @param {string} whichAxes `xy`, 'x', or 'y'
|
||||
* @param {number} animationDuration Duration of the animation of the redraw in milliseconds
|
||||
*/
|
||||
function doZoom(chart, percentZoomX, percentZoomY, focalPoint, whichAxes, animationDuration) {
|
||||
var ca = chart.chartArea;
|
||||
if (!focalPoint) {
|
||||
focalPoint = {
|
||||
x: (ca.left + ca.right) / 2,
|
||||
y: (ca.top + ca.bottom) / 2,
|
||||
};
|
||||
}
|
||||
|
||||
var zoomOptions = chart.$zoom._options.zoom;
|
||||
|
||||
if (zoomOptions.enabled) {
|
||||
storeOriginalOptions(chart);
|
||||
// Do the zoom here
|
||||
var zoomMode = typeof zoomOptions.mode === 'function' ? zoomOptions.mode({chart: chart}) : zoomOptions.mode;
|
||||
|
||||
// Which axe should be modified when figers were used.
|
||||
var _whichAxes;
|
||||
if (zoomMode === 'xy' && whichAxes !== undefined) {
|
||||
// based on fingers positions
|
||||
_whichAxes = whichAxes;
|
||||
} else {
|
||||
// no effect
|
||||
_whichAxes = 'xy';
|
||||
}
|
||||
|
||||
helpers.each(chart.scales, function(scale) {
|
||||
if (scale.isHorizontal() && directionEnabled(zoomMode, 'x', chart) && directionEnabled(_whichAxes, 'x', chart)) {
|
||||
zoomOptions.scaleAxes = 'x';
|
||||
zoomScale(scale, percentZoomX, focalPoint, zoomOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(zoomMode, 'y', chart) && directionEnabled(_whichAxes, 'y', chart)) {
|
||||
// Do Y zoom
|
||||
zoomOptions.scaleAxes = 'y';
|
||||
zoomScale(scale, percentZoomY, focalPoint, zoomOptions);
|
||||
}
|
||||
});
|
||||
|
||||
if (animationDuration) {
|
||||
// needs to create specific animation mode
|
||||
if (!chart.options.animation.zoom) {
|
||||
chart.options.animation.zoom = {
|
||||
duration: animationDuration,
|
||||
easing: 'easeOutQuad',
|
||||
};
|
||||
}
|
||||
chart.update('zoom');
|
||||
} else {
|
||||
chart.update('none');
|
||||
}
|
||||
|
||||
if (typeof zoomOptions.onZoom === 'function') {
|
||||
zoomOptions.onZoom({chart: chart});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function panCategoryScale(scale, delta, panOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var offsetAmt = Math.max(scale.ticks.length, 1);
|
||||
var panSpeed = panOptions.speed;
|
||||
var minIndex = scale.min;
|
||||
var step = Math.round(scale.width / (offsetAmt * panSpeed));
|
||||
var maxIndex;
|
||||
|
||||
zoomNS.panCumulativeDelta += delta;
|
||||
|
||||
minIndex = zoomNS.panCumulativeDelta > step ? Math.max(0, minIndex - 1) : zoomNS.panCumulativeDelta < -step ? Math.min(lastLabelIndex - offsetAmt + 1, minIndex + 1) : minIndex;
|
||||
zoomNS.panCumulativeDelta = minIndex !== scale.min ? 0 : zoomNS.panCumulativeDelta;
|
||||
|
||||
maxIndex = Math.min(lastLabelIndex, minIndex + offsetAmt - 1);
|
||||
|
||||
scale.options.min = rangeMinLimiter(panOptions, labels[minIndex]);
|
||||
scale.options.max = rangeMaxLimiter(panOptions, labels[maxIndex]);
|
||||
}
|
||||
|
||||
function panNumericalScale(scale, delta, panOptions) {
|
||||
var scaleOpts = scale.options;
|
||||
var prevStart = scale.min;
|
||||
var prevEnd = scale.max;
|
||||
var newMin = scale.getValueForPixel(scale.getPixelForValue(prevStart) - delta);
|
||||
var newMax = scale.getValueForPixel(scale.getPixelForValue(prevEnd) - delta);
|
||||
var rangeMin = newMin;
|
||||
var rangeMax = newMax;
|
||||
var diff;
|
||||
|
||||
if (panOptions.scaleAxes && panOptions.rangeMin &&
|
||||
!helpers.isNullOrUndef(panOptions.rangeMin[panOptions.scaleAxes])) {
|
||||
rangeMin = panOptions.rangeMin[panOptions.scaleAxes];
|
||||
}
|
||||
if (panOptions.scaleAxes && panOptions.rangeMax &&
|
||||
!helpers.isNullOrUndef(panOptions.rangeMax[panOptions.scaleAxes])) {
|
||||
rangeMax = panOptions.rangeMax[panOptions.scaleAxes];
|
||||
}
|
||||
|
||||
if (newMin >= rangeMin && newMax <= rangeMax) {
|
||||
scaleOpts.ticks.min = newMin;
|
||||
scaleOpts.ticks.max = newMax;
|
||||
} else if (newMin < rangeMin) {
|
||||
diff = prevStart - rangeMin;
|
||||
scaleOpts.ticks.min = rangeMin;
|
||||
scaleOpts.ticks.max = prevEnd - diff;
|
||||
} else if (newMax > rangeMax) {
|
||||
diff = rangeMax - prevEnd;
|
||||
scaleOpts.ticks.max = rangeMax;
|
||||
scaleOpts.ticks.min = prevStart + diff;
|
||||
}
|
||||
}
|
||||
|
||||
function panScale(scale, delta, panOptions) {
|
||||
var fn = panFunctions[scale.type];
|
||||
if (fn) {
|
||||
fn(scale, delta, panOptions);
|
||||
}
|
||||
}
|
||||
|
||||
function doPan(chartInstance, deltaX, deltaY) {
|
||||
storeOriginalOptions(chartInstance);
|
||||
var panOptions = chartInstance.$zoom._options.pan;
|
||||
if (panOptions.enabled) {
|
||||
var panMode = typeof panOptions.mode === 'function' ? panOptions.mode({chart: chartInstance}) : panOptions.mode;
|
||||
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
if (scale.isHorizontal() && directionEnabled(panMode, 'x', chartInstance) && deltaX !== 0) {
|
||||
panOptions.scaleAxes = 'x';
|
||||
panScale(scale, deltaX, panOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(panMode, 'y', chartInstance) && deltaY !== 0) {
|
||||
panOptions.scaleAxes = 'y';
|
||||
panScale(scale, deltaY, panOptions);
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.update('none');
|
||||
|
||||
if (typeof panOptions.onPan === 'function') {
|
||||
panOptions.onPan({chart: chartInstance});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getXAxis(chartInstance) {
|
||||
var scales = chartInstance.scales;
|
||||
var scaleIds = Object.keys(scales);
|
||||
for (var i = 0; i < scaleIds.length; i++) {
|
||||
var scale = scales[scaleIds[i]];
|
||||
|
||||
if (scale.isHorizontal()) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getYAxis(chartInstance) {
|
||||
var scales = chartInstance.scales;
|
||||
var scaleIds = Object.keys(scales);
|
||||
for (var i = 0; i < scaleIds.length; i++) {
|
||||
var scale = scales[scaleIds[i]];
|
||||
|
||||
if (!scale.isHorizontal()) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store these for later
|
||||
zoomNS.zoomFunctions.category = zoomCategoryScale;
|
||||
zoomNS.zoomFunctions.time = zoomNumericalScale;
|
||||
zoomNS.zoomFunctions.linear = zoomNumericalScale;
|
||||
zoomNS.zoomFunctions.logarithmic = zoomNumericalScale;
|
||||
zoomNS.panFunctions.category = panCategoryScale;
|
||||
zoomNS.panFunctions.time = panNumericalScale;
|
||||
zoomNS.panFunctions.linear = panNumericalScale;
|
||||
zoomNS.panFunctions.logarithmic = panNumericalScale;
|
||||
// Globals for category pan and zoom
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
|
||||
// Chartjs Zoom Plugin
|
||||
var zoomPlugin = {
|
||||
id: 'zoom',
|
||||
|
||||
defaults: {
|
||||
pan: {
|
||||
enabled: false,
|
||||
mode: 'xy',
|
||||
speed: 20,
|
||||
threshold: 10
|
||||
},
|
||||
zoom: {
|
||||
enabled: false,
|
||||
mode: 'xy',
|
||||
sensitivity: 3,
|
||||
speed: 0.1
|
||||
}
|
||||
},
|
||||
|
||||
afterInit: function(chartInstance) {
|
||||
|
||||
chartInstance.resetZoom = function() {
|
||||
storeOriginalOptions(chartInstance);
|
||||
var originalOptions = chartInstance.$zoom._originalOptions;
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
|
||||
var options = scale.options;
|
||||
if (originalOptions[scale.id]) {
|
||||
options.min = originalOptions[scale.id].min;
|
||||
options.max = originalOptions[scale.id].max;
|
||||
} else {
|
||||
delete options.min;
|
||||
delete options.max;
|
||||
}
|
||||
});
|
||||
chartInstance.update();
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
beforeUpdate: function(chart, args, options) {
|
||||
resolveOptions(chart, options);
|
||||
},
|
||||
|
||||
beforeInit: function(chartInstance, pluginOptions) {
|
||||
chartInstance.$zoom = {
|
||||
_originalOptions: {}
|
||||
};
|
||||
var node = chartInstance.$zoom._node = chartInstance.ctx.canvas;
|
||||
resolveOptions(chartInstance, pluginOptions);
|
||||
|
||||
var options = chartInstance.$zoom._options;
|
||||
var panThreshold = options.pan && options.pan.threshold;
|
||||
|
||||
chartInstance.$zoom._mouseDownHandler = function(event) {
|
||||
node.addEventListener('mousemove', chartInstance.$zoom._mouseMoveHandler);
|
||||
chartInstance.$zoom._dragZoomStart = event;
|
||||
};
|
||||
|
||||
chartInstance.$zoom._mouseMoveHandler = function(event) {
|
||||
if (chartInstance.$zoom._dragZoomStart) {
|
||||
chartInstance.$zoom._dragZoomEnd = event;
|
||||
chartInstance.update('none');
|
||||
}
|
||||
};
|
||||
|
||||
chartInstance.$zoom._mouseUpHandler = function(event) {
|
||||
if (!chartInstance.$zoom._dragZoomStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.removeEventListener('mousemove', chartInstance.$zoom._mouseMoveHandler);
|
||||
|
||||
var beginPoint = chartInstance.$zoom._dragZoomStart;
|
||||
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
var startX = Math.min(beginPoint.clientX, event.clientX) - offsetX;
|
||||
var endX = Math.max(beginPoint.clientX, event.clientX) - offsetX;
|
||||
|
||||
var offsetY = beginPoint.target.getBoundingClientRect().top;
|
||||
var startY = Math.min(beginPoint.clientY, event.clientY) - offsetY;
|
||||
var endY = Math.max(beginPoint.clientY, event.clientY) - offsetY;
|
||||
|
||||
var dragDistanceX = endX - startX;
|
||||
var dragDistanceY = endY - startY;
|
||||
|
||||
// Remove drag start and end before chart update to stop drawing selected area
|
||||
chartInstance.$zoom._dragZoomStart = null;
|
||||
chartInstance.$zoom._dragZoomEnd = null;
|
||||
|
||||
var zoomThreshold = (options.zoom && options.zoom.threshold) || 0;
|
||||
if (dragDistanceX <= zoomThreshold && dragDistanceY <= zoomThreshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chartArea = chartInstance.chartArea;
|
||||
|
||||
var zoomOptions = chartInstance.$zoom._options.zoom;
|
||||
var chartDistanceX = chartArea.right - chartArea.left;
|
||||
var xEnabled = directionEnabled(zoomOptions.mode, 'x', chartInstance);
|
||||
var zoomX = xEnabled && dragDistanceX ? 1 + ((chartDistanceX - dragDistanceX) / chartDistanceX) : 1;
|
||||
|
||||
var chartDistanceY = chartArea.bottom - chartArea.top;
|
||||
var yEnabled = directionEnabled(zoomOptions.mode, 'y', chartInstance);
|
||||
var zoomY = yEnabled && dragDistanceY ? 1 + ((chartDistanceY - dragDistanceY) / chartDistanceY) : 1;
|
||||
|
||||
doZoom(chartInstance, zoomX, zoomY, {
|
||||
x: (startX - chartArea.left) / (1 - dragDistanceX / chartDistanceX) + chartArea.left,
|
||||
y: (startY - chartArea.top) / (1 - dragDistanceY / chartDistanceY) + chartArea.top
|
||||
}, undefined, zoomOptions.drag.animationDuration);
|
||||
|
||||
if (typeof zoomOptions.onZoomComplete === 'function') {
|
||||
zoomOptions.onZoomComplete({chart: chartInstance});
|
||||
}
|
||||
};
|
||||
|
||||
var _scrollTimeout = null;
|
||||
var _lastWheelEvent = 0;
|
||||
chartInstance.$zoom._wheelHandler = function(event) {
|
||||
// Prevent the event from triggering the default behavior (eg. Content scrolling).
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// Firefox always fires the wheel event twice:
|
||||
// First without the delta and right after that once with the delta properties.
|
||||
if (typeof event.deltaY === 'undefined' || event.deltaY == 0) { // M.Z. deltaY == 0
|
||||
return;
|
||||
}
|
||||
|
||||
var now = performance.now();
|
||||
if (now < _lastWheelEvent + 50) { // M.Z. touchpad events are fired more frequently -> skip when too quick
|
||||
return;
|
||||
}
|
||||
_lastWheelEvent = now;
|
||||
var rect = event.target.getBoundingClientRect();
|
||||
var offsetX = event.clientX - rect.left;
|
||||
var offsetY = event.clientY - rect.top;
|
||||
|
||||
var center = {
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
};
|
||||
|
||||
var zoomOptions = chartInstance.$zoom._options.zoom;
|
||||
var speedPercent = zoomOptions.speed;
|
||||
|
||||
if (event.deltaY >= 0) {
|
||||
speedPercent = -speedPercent;
|
||||
}
|
||||
doZoom(chartInstance, 1 + speedPercent, 1 + speedPercent, center);
|
||||
|
||||
clearTimeout(_scrollTimeout);
|
||||
_scrollTimeout = setTimeout(function() {
|
||||
if (typeof zoomOptions.onZoomComplete === 'function') {
|
||||
zoomOptions.onZoomComplete({chart: chartInstance});
|
||||
}
|
||||
}, 250);
|
||||
};
|
||||
|
||||
if (Hammer) {
|
||||
var mc = new Hammer.Manager(node);
|
||||
mc.add(new Hammer.Pinch());
|
||||
mc.add(new Hammer.Pan({
|
||||
threshold: panThreshold
|
||||
}));
|
||||
|
||||
// Hammer reports the total scaling. We need the incremental amount
|
||||
var currentPinchScaling;
|
||||
var handlePinch = function(e) {
|
||||
var diff = 1 / (currentPinchScaling) * e.scale;
|
||||
var rect = e.target.getBoundingClientRect();
|
||||
var offsetX = e.center.x - rect.left;
|
||||
var offsetY = e.center.y - rect.top;
|
||||
var center = {
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
};
|
||||
|
||||
// fingers position difference
|
||||
var x = Math.abs(e.pointers[0].clientX - e.pointers[1].clientX);
|
||||
var y = Math.abs(e.pointers[0].clientY - e.pointers[1].clientY);
|
||||
|
||||
// diagonal fingers will change both (xy) axes
|
||||
var p = x / y;
|
||||
var xy;
|
||||
if (p > 0.3 && p < 1.7) {
|
||||
xy = 'xy';
|
||||
} else if (x > y) {
|
||||
xy = 'x'; // x axis
|
||||
} else {
|
||||
xy = 'y'; // y axis
|
||||
}
|
||||
|
||||
doZoom(chartInstance, diff, diff, center, xy);
|
||||
|
||||
var zoomOptions = chartInstance.$zoom._options.zoom;
|
||||
if (typeof zoomOptions.onZoomComplete === 'function') {
|
||||
zoomOptions.onZoomComplete({chart: chartInstance});
|
||||
}
|
||||
|
||||
// Keep track of overall scale
|
||||
currentPinchScaling = e.scale;
|
||||
};
|
||||
|
||||
mc.on('pinchstart', function() {
|
||||
currentPinchScaling = 1; // reset tracker
|
||||
});
|
||||
mc.on('pinch', handlePinch);
|
||||
mc.on('pinchend', function(e) {
|
||||
handlePinch(e);
|
||||
currentPinchScaling = null; // reset
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
});
|
||||
|
||||
var currentDeltaX = null;
|
||||
var currentDeltaY = null;
|
||||
var panning = false;
|
||||
var handlePan = function(e) {
|
||||
if (currentDeltaX !== null && currentDeltaY !== null) {
|
||||
panning = true;
|
||||
var deltaX = e.deltaX - currentDeltaX;
|
||||
var deltaY = e.deltaY - currentDeltaY;
|
||||
currentDeltaX = e.deltaX;
|
||||
currentDeltaY = e.deltaY;
|
||||
doPan(chartInstance, deltaX, deltaY);
|
||||
}
|
||||
};
|
||||
|
||||
mc.on('panstart', function(e) {
|
||||
currentDeltaX = 0;
|
||||
currentDeltaY = 0;
|
||||
handlePan(e);
|
||||
});
|
||||
mc.on('panmove', handlePan);
|
||||
mc.on('panend', function() {
|
||||
currentDeltaX = null;
|
||||
currentDeltaY = null;
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
setTimeout(function() {
|
||||
panning = false;
|
||||
}, 500);
|
||||
|
||||
var panOptions = chartInstance.$zoom._options.pan;
|
||||
if (typeof panOptions.onPanComplete === 'function') {
|
||||
panOptions.onPanComplete({chart: chartInstance});
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.$zoom._ghostClickHandler = function(e) {
|
||||
if (panning && e.cancelable) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
node.addEventListener('click', chartInstance.$zoom._ghostClickHandler);
|
||||
|
||||
chartInstance._mc = mc;
|
||||
}
|
||||
},
|
||||
|
||||
beforeDatasetsDraw: function(chartInstance) {
|
||||
var ctx = chartInstance.ctx;
|
||||
|
||||
if (chartInstance.$zoom._dragZoomEnd) {
|
||||
var xAxis = getXAxis(chartInstance);
|
||||
var yAxis = getYAxis(chartInstance);
|
||||
var beginPoint = chartInstance.$zoom._dragZoomStart;
|
||||
var endPoint = chartInstance.$zoom._dragZoomEnd;
|
||||
|
||||
var startX = xAxis.left;
|
||||
var endX = xAxis.right;
|
||||
var startY = yAxis.top;
|
||||
var endY = yAxis.bottom;
|
||||
|
||||
if (directionEnabled(chartInstance.$zoom._options.zoom.mode, 'x', chartInstance)) {
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
startX = Math.min(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
endX = Math.max(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
}
|
||||
|
||||
if (directionEnabled(chartInstance.$zoom._options.zoom.mode, 'y', chartInstance)) {
|
||||
var offsetY = beginPoint.target.getBoundingClientRect().top;
|
||||
startY = Math.min(beginPoint.clientY, endPoint.clientY) - offsetY;
|
||||
endY = Math.max(beginPoint.clientY, endPoint.clientY) - offsetY;
|
||||
}
|
||||
|
||||
var rectWidth = endX - startX;
|
||||
var rectHeight = endY - startY;
|
||||
var dragOptions = chartInstance.$zoom._options.zoom.drag;
|
||||
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = dragOptions.backgroundColor || 'rgba(225,225,225,0.3)';
|
||||
ctx.fillRect(startX, startY, rectWidth, rectHeight);
|
||||
|
||||
if (dragOptions.borderWidth > 0) {
|
||||
ctx.lineWidth = dragOptions.borderWidth;
|
||||
ctx.strokeStyle = dragOptions.borderColor || 'rgba(225,225,225)';
|
||||
ctx.strokeRect(startX, startY, rectWidth, rectHeight);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function(chartInstance) {
|
||||
if (!chartInstance.$zoom) {
|
||||
return;
|
||||
}
|
||||
var props = chartInstance.$zoom;
|
||||
var node = props._node;
|
||||
|
||||
node.removeEventListener('mousedown', props._mouseDownHandler);
|
||||
node.removeEventListener('mousemove', props._mouseMoveHandler);
|
||||
node.ownerDocument.removeEventListener('mouseup', props._mouseUpHandler);
|
||||
node.removeEventListener('wheel', props._wheelHandler);
|
||||
node.removeEventListener('click', props._ghostClickHandler);
|
||||
|
||||
delete chartInstance.$zoom;
|
||||
|
||||
var mc = chartInstance._mc;
|
||||
if (mc) {
|
||||
mc.remove('pinchstart');
|
||||
mc.remove('pinch');
|
||||
mc.remove('pinchend');
|
||||
mc.remove('panstart');
|
||||
mc.remove('pan');
|
||||
mc.remove('panend');
|
||||
mc.destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Chart.plugins.register(zoomPlugin);
|
||||
//export default zoomPlugin;
|
||||
@@ -94,7 +94,7 @@ function handleUpdateMessage(src, message) {
|
||||
document.title = "SEA "+clientTitle + " " + message.title;
|
||||
}
|
||||
var header = document.getElementById("header");
|
||||
header.setAttribute("style", "width: auto;");
|
||||
header.style.width = 'auto';
|
||||
header.innerHTML = clientTitle;
|
||||
console.log('ID', initCommands);
|
||||
nextInitCommand();
|
||||
@@ -137,6 +137,7 @@ function handleUpdateMessage(src, message) {
|
||||
break;
|
||||
// graph-message: Evokes redraw of graphics.
|
||||
case "graph":
|
||||
alert('obsolete code "graph" called')
|
||||
console.log("graph");
|
||||
createCharts2(message.graph);
|
||||
break;
|
||||
@@ -169,6 +170,7 @@ function handleUpdateMessage(src, message) {
|
||||
}
|
||||
|
||||
function htmlEscape(str) {
|
||||
str = "" + str;
|
||||
if (!str) return "";
|
||||
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g,
|
||||
''').replace(/</g, '<').replace(/>/g, '>');
|
||||
@@ -196,8 +198,9 @@ function updateValues(message, src) {
|
||||
var component = message.updates[i];
|
||||
var value = component.value;
|
||||
var matches = document.getElementsByName(component.name);
|
||||
|
||||
for (var j = 0; j < matches.length; j++) {
|
||||
var type = matches[j].getAttribute("__ctype__");
|
||||
var type = matches[j].__ctype__;
|
||||
if (type == "rdonly") {
|
||||
var text = htmlEscape(value);
|
||||
if (text) {
|
||||
@@ -207,8 +210,7 @@ function updateValues(message, src) {
|
||||
var row = matches[j].parentNode.parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
var mval = matches[j].value;
|
||||
var oldValue = matches[j].getAttribute("oldValue");
|
||||
if (oldValue === null) oldValue = mval;
|
||||
var oldValue = ('oldValue' in matches[j]) ? matches[j].oldValue : mval;
|
||||
if (value != mval && parseFloat(value) != parseFloat(mval) && value != oldValue) {
|
||||
if (matches[j] == document.activeElement
|
||||
|| oldValue != mval) {
|
||||
@@ -217,12 +219,13 @@ function updateValues(message, src) {
|
||||
matches[j].value = value;
|
||||
}
|
||||
}
|
||||
matches[j].setAttribute("actualValue", value);
|
||||
matches[j].actualValue = value;
|
||||
resizeTextfield(matches[j]);
|
||||
} else if (type == "checkbox") {
|
||||
var row = matches[j].parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
matches[j].checked = value == 1 && value == "1";
|
||||
console.log('CBX', matches[j].name, message, Boolean(value && value != 'false'));
|
||||
matches[j].checked = Boolean(value && value != 'false');
|
||||
} else if (type == "enum") {
|
||||
matches[j].style.display = "block";
|
||||
var row = matches[j].parentNode.parentNode;
|
||||
@@ -277,14 +280,16 @@ function successHandler(s, message) {
|
||||
}
|
||||
if (message.path == "main") {
|
||||
// Happens only initially or at device change.
|
||||
for (var sLocal = 0; sLocal < MAXBLOCK; sLocal++) {
|
||||
for (var sLocal = 0; sLocal < 2; sLocal++) { // was up to MAXBLOCK
|
||||
insertSlide(sLocal, message.title, "main", createContent(
|
||||
sLocal, message));
|
||||
}
|
||||
insertSlide(2, "", "parameters", createContent(2, {components:[]}));
|
||||
} else {
|
||||
if (s < 0) { // redraw: check for slides in all swiper instances
|
||||
for (var isw = 0; isw < MAXBLOCK; isw ++) {
|
||||
var slide = findSlide(isw, message.path);
|
||||
var isl = findSlide(isw, message.path);
|
||||
var slide = swiper[isl].slides[i];
|
||||
if (slide) {
|
||||
console.log("redraw", isw);
|
||||
replaceSlideContent(slide, message.title,
|
||||
@@ -292,8 +297,10 @@ function successHandler(s, message) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
insertSlide(s, message.title, message.path, createContent(s,
|
||||
message));
|
||||
// insertSlide(s, message.title, message.path, createContent(s, message));
|
||||
let sLocal = paramSlider[s];
|
||||
isl = insertSlide(sLocal, message.title, "parameters", createContent(sLocal, message));
|
||||
swiper[sLocal].slideTo(isl); /* go to found slide */
|
||||
}
|
||||
}
|
||||
nextInitCommand();
|
||||
@@ -360,6 +367,7 @@ function successHandler(s, message) {
|
||||
if (debugCommunication) {
|
||||
console.log("graph-draw", message);
|
||||
}
|
||||
alert('obsolete code graph-draw called')
|
||||
createCharts2(message.graph);
|
||||
nextInitCommand();
|
||||
// Request for updates.
|
||||
|
||||
@@ -9,8 +9,8 @@ function createContentConsole(s) {
|
||||
// Creates input-textfield and texarea showing console-history.
|
||||
|
||||
var commandline = document.createElement('input');
|
||||
commandline.setAttribute("type", "text");
|
||||
commandline.setAttribute("class", "row commandline");
|
||||
commandline.type = "text";
|
||||
commandline.classList.add("row", "commandline");
|
||||
|
||||
commandline.onkeydown = function (e) {
|
||||
//console.log(histIndex);
|
||||
@@ -38,10 +38,10 @@ function createContentConsole(s) {
|
||||
}
|
||||
};
|
||||
|
||||
commandline.setAttribute("autocomplete", "on");
|
||||
commandline.autocomplete = "on";
|
||||
|
||||
var wrapper = document.createElement('form');
|
||||
wrapper.setAttribute("class", "commandline-wrapper");
|
||||
wrapper.classList.add("commandline-wrapper");
|
||||
|
||||
wrapper.onsubmit = function (e) {
|
||||
e.preventDefault();
|
||||
@@ -53,14 +53,14 @@ function createContentConsole(s) {
|
||||
commandline.value = "";
|
||||
};
|
||||
|
||||
wrapper.setAttribute("method", 'GET');
|
||||
wrapper.method = "GET";
|
||||
wrapper.appendChild(commandline);
|
||||
|
||||
var history = document.createElement('div');
|
||||
history.setAttribute("class", "history");
|
||||
history.classList.add("history");
|
||||
|
||||
var content = document.createElement('div');
|
||||
content.setAttribute("class", "content-console");
|
||||
content.classList.add("content-console");
|
||||
content.appendChild(wrapper);
|
||||
content.appendChild(history);
|
||||
return content;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+136
-195
@@ -13,7 +13,7 @@ function getGroup(s, name) {
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < swiper[s].slides.length; i++) {
|
||||
var slideType = swiper[s].slides[i].getAttribute("slide-type");
|
||||
var slideType = swiper[s].slides[i].slideType;
|
||||
if (slideType == name) {
|
||||
found = true;
|
||||
swiper[s].slideTo(i);
|
||||
@@ -33,56 +33,20 @@ function sendCommand(s, command) {
|
||||
|
||||
function createContent(s, message) {
|
||||
// Depending on the message received from the server the content of the
|
||||
// group
|
||||
// is created dynamically. Handles draw-message.
|
||||
// group is created dynamically. Handles draw-message.
|
||||
|
||||
var content = document.createElement('div');
|
||||
content.setAttribute("class", "content");
|
||||
content.classList.add("content");
|
||||
// Process components of the message
|
||||
for (var i = 0; i < message.components.length; i++) {
|
||||
var component = message.components[i];
|
||||
var name = component.name;
|
||||
var type = component.type;
|
||||
var title = name;
|
||||
if ("title" in component)
|
||||
title = component.title;
|
||||
var info = component.info;
|
||||
switch (type) {
|
||||
case "group":
|
||||
content.appendChild(createLink(s, name, title));
|
||||
break;
|
||||
case "rdonly":
|
||||
if ("link" in component) {
|
||||
content.appendChild(createReadOnlyInstrLink(s, name, title,
|
||||
component.link, info));
|
||||
} else {
|
||||
content.appendChild(createReadOnly(s, name, title, info));
|
||||
}
|
||||
break;
|
||||
case "rdlink":
|
||||
content.appendChild(createReadOnlyGroupLink(s, name, title, info));
|
||||
break;
|
||||
case "input":
|
||||
content.appendChild(createInput(s, name, title,
|
||||
info));
|
||||
break;
|
||||
case "checkbox":
|
||||
content.appendChild(createCheckbox(s, name, title,
|
||||
info));
|
||||
break;
|
||||
case "enum":
|
||||
content.appendChild(createSelection(s, name, title,
|
||||
component.enum_names, info));
|
||||
break;
|
||||
case "pushbutton":
|
||||
console.log(component);
|
||||
console.log(component.info);
|
||||
content.appendChild(createPushButton(s, name, title,
|
||||
info));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!("title" in component))
|
||||
component.title = name;
|
||||
if (!("command" in component))
|
||||
component.command = name;
|
||||
createFunc = window['create_' + component.type + '_row']
|
||||
if (createFunc)
|
||||
content.appendChild(createFunc(s, component))
|
||||
}
|
||||
return content;
|
||||
}
|
||||
@@ -96,84 +60,50 @@ function gotoGroups(slideNames) {
|
||||
}
|
||||
}
|
||||
|
||||
function createLink(s, name, title) {
|
||||
function create_group_row(s, component) {
|
||||
// Creates row-element containing link.
|
||||
var title = component.title;
|
||||
|
||||
var row = document.createElement('row');
|
||||
row.setAttribute("id", name);
|
||||
row.setAttribute("name", title);
|
||||
row.setAttribute("class", "interactive row link");
|
||||
row.setAttribute("tabindex", 0);
|
||||
row.id = component.name;
|
||||
row.name = title;
|
||||
row.classList.add("interactive", "row", "link");
|
||||
row.tabIndex = "0";
|
||||
|
||||
row.onclick = function () {
|
||||
var slideNames = getSlideNames();
|
||||
slideNames[s] = name;
|
||||
slideNames[s] = component.name;
|
||||
document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
|
||||
history.pushState({func: "gotoGroups", funarg: slideNames.join("%20")}, document.title, "#" + slideNames.join("%20"));
|
||||
getGroup(s, name);
|
||||
}
|
||||
|
||||
if (title === "console" || title === "device config") {
|
||||
row.setAttribute("class", "interactive row link link-static");
|
||||
row.classList.add("interactive", "row", "link", "link-static");
|
||||
row.innerHTML = "console";
|
||||
}
|
||||
row.innerHTML = title;
|
||||
return row;
|
||||
}
|
||||
|
||||
function createReadOnly(s, name, title, info) {
|
||||
// Creates row-element containing read-only-item.
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createReadOnlyGroupLink(s, name, title, info) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
// for secop
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.setAttribute("class", "interactive link");
|
||||
|
||||
left.onclick = function () {
|
||||
getGroup(s, title);
|
||||
}
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createReadOnlyInstrLink(s, name, title, link, info) {
|
||||
function create_rdonly_row(s, component) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
|
||||
// var left = createTitle(title, info);
|
||||
var link = component.link;
|
||||
if (!link) // simple rdonly
|
||||
return appendToContent(component, createTitle(component),
|
||||
createParElement(component));
|
||||
|
||||
// with link
|
||||
var left = document.createElement('a');
|
||||
left.setAttribute("class", "col-left");
|
||||
left.innerHTML = title;
|
||||
left.classList.add("col-left");
|
||||
left.innerHTML = component.title;
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.setAttribute("class", "interactive link");
|
||||
left.id = component.name;
|
||||
left.name = component.title;
|
||||
left.classList.add("interactive", "link");
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
row = appendToContent(info, left, right);
|
||||
row = appendToContent(component, left, createParElement(component));
|
||||
row.onclick = function () {
|
||||
this.style.backgroundColor = "orangered";
|
||||
left.click();
|
||||
@@ -184,31 +114,46 @@ function createReadOnlyInstrLink(s, name, title, link, info) {
|
||||
left.href = link;
|
||||
}
|
||||
|
||||
row.setAttribute("class", "row clickable");
|
||||
row.classList.add("row", "clickable");
|
||||
return row;
|
||||
}
|
||||
|
||||
function createPushButton(s, name, title, info) {
|
||||
function create_rdlink_row(s, component) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
var name = component.name;
|
||||
|
||||
var left = createTitle(component);
|
||||
left.id = component.name;
|
||||
left.name = component.title; // or setAttribute('name'.. ?
|
||||
left.classList.add("interactive", "link");
|
||||
|
||||
left.onclick = function () {
|
||||
getGroup(s, component.title);
|
||||
}
|
||||
return appendToContent(component, left, createParElement(component));
|
||||
}
|
||||
|
||||
function create_pushbutton_row(s, component) {
|
||||
// Creates row-element containing a push button
|
||||
|
||||
var left = createTitle(title, info);
|
||||
var name = component.name;
|
||||
var command = component.command;
|
||||
var left = createTitle(component);
|
||||
console.log(info);
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.id = component.name;
|
||||
left.name = component.title;
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right clickable push-button");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
var right = createParElement(component);
|
||||
right.classList.add("clickable", "push-button");
|
||||
|
||||
row = appendToContent(info, left, right);
|
||||
row = appendToContent(component, left, right);
|
||||
right.onclick = function () {
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
right.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name);
|
||||
sendCommand(s, command);
|
||||
} else {
|
||||
prompt = true;
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
@@ -223,7 +168,7 @@ function createPushButton(s, name, title, info) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name);
|
||||
sendCommand(s, command);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
@@ -232,23 +177,23 @@ function createPushButton(s, name, title, info) {
|
||||
}
|
||||
}
|
||||
|
||||
row.setAttribute("class", "row");
|
||||
row.classList.add("row");
|
||||
return row;
|
||||
}
|
||||
|
||||
function createInput(s, name, title, info) {
|
||||
function create_input_row(s, component) {
|
||||
// Creates row-element containing input-item.
|
||||
|
||||
if (info) {
|
||||
var infoBox = createInfo(title, info);
|
||||
}
|
||||
var left = createTitle(title, info);
|
||||
var name = component.name;
|
||||
var command = component.command;
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("type", "text");
|
||||
input.setAttribute("class", "input-text");
|
||||
input.setAttribute("name", name);
|
||||
input.setAttribute("__ctype__", "input");
|
||||
if (info) {
|
||||
var infoBox = createInfo(component);
|
||||
}
|
||||
var left = createTitle(component);
|
||||
|
||||
var input = createParElement(component, 'input', 'input-text');
|
||||
input.type = "text";
|
||||
input.style.width = "100px";
|
||||
input.addEventListener("focus", function(evt) {
|
||||
let elm = evt.target;
|
||||
@@ -258,7 +203,7 @@ function createInput(s, name, title, info) {
|
||||
input.onkeydown = function (e) {
|
||||
if (e.which === 27 || e.key == "Escape") {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("oldValue");
|
||||
input.value = intput.oldValue;
|
||||
resizeTextfield(input);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
@@ -266,9 +211,9 @@ function createInput(s, name, title, info) {
|
||||
}
|
||||
|
||||
input.onfocus = function () {
|
||||
input.setAttribute("oldValue", input.value);
|
||||
input.oldValue = input.value;
|
||||
|
||||
if (isTouchDevice())
|
||||
if (isTouchDevice)
|
||||
setTimeout(function () {
|
||||
posTextfield(s, left);
|
||||
}, 1);
|
||||
@@ -280,11 +225,9 @@ function createInput(s, name, title, info) {
|
||||
}
|
||||
var row = left.parentNode;
|
||||
var value = input.value;
|
||||
var oldValue = input.getAttribute("oldValue") || value;
|
||||
if (!input.hasAttribute("actualValue")) {
|
||||
input.setAttribute("actualValue", oldValue);
|
||||
}
|
||||
var actualValue = input.getAttribute("actualValue");
|
||||
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;
|
||||
@@ -306,12 +249,12 @@ function createInput(s, name, title, info) {
|
||||
}, 3600000);
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
sendCommand(s, command + " " + value);
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("actualValue");
|
||||
input.value = input.actualValue;
|
||||
resizeTextfield(input);
|
||||
row.style.backgroundColor = "white";
|
||||
prompt = false;
|
||||
@@ -321,16 +264,12 @@ function createInput(s, name, title, info) {
|
||||
var form = document.createElement('form');
|
||||
form.onsubmit = function (e) {
|
||||
e.preventDefault();
|
||||
// remove following check: sometimes we want to send a command even with an unchanged value
|
||||
//if (input.value === input.getAttribute("oldValue")) {
|
||||
// // nothing to do.
|
||||
// return false;
|
||||
//}
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + input.value);
|
||||
input.blur();
|
||||
} else {
|
||||
var value = input.value
|
||||
prompt = true;
|
||||
@@ -346,23 +285,21 @@ function createInput(s, name, title, info) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
sendCommand(s, command + " " + value);
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("oldValue");
|
||||
input.value = input.oldValue;
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
form.appendChild(input);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
var right = createParElement(component);
|
||||
right.appendChild(form);
|
||||
return appendToContent(info, left, right);
|
||||
return appendToContent(component, left, right);
|
||||
}
|
||||
|
||||
function posTextfield(s, left) {
|
||||
@@ -383,16 +320,14 @@ function resizeTextfield(input) {
|
||||
}
|
||||
}
|
||||
|
||||
function createCheckbox(s, name, title, info) {
|
||||
function create_checkbox_row(s, component) {
|
||||
// Creates row-element containing checkbox-item
|
||||
var command = component.command;
|
||||
|
||||
var left = createTitle(title, info);
|
||||
var left = createTitle(component);
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("type", "checkbox");
|
||||
input.setAttribute("name", name);
|
||||
input.setAttribute("__ctype__", "checkbox");
|
||||
input.setAttribute("class", "parameter-checkbox");
|
||||
var input = createParElement(component, 'input', 'parameter-checkbox');
|
||||
input.type = "checkbox";
|
||||
|
||||
input.onkeyup = function (e) {
|
||||
if (e.keyCode === 32) {
|
||||
@@ -401,8 +336,8 @@ function createCheckbox(s, name, title, info) {
|
||||
}
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.setAttribute("for", input);
|
||||
label.setAttribute("class", "parameter-label");
|
||||
label.for = input;
|
||||
label.classList.add("parameter-label");
|
||||
|
||||
label.onclick = function () {
|
||||
handleCheckbox();
|
||||
@@ -420,7 +355,7 @@ function createCheckbox(s, name, title, info) {
|
||||
input.checked = true;
|
||||
}
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
sendCommand(s, command + " " + value);
|
||||
} else {
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
@@ -441,7 +376,7 @@ function createCheckbox(s, name, title, info) {
|
||||
input.checked = true;
|
||||
}
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
sendCommand(s, command + " " + value);
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
});
|
||||
@@ -449,32 +384,32 @@ function createCheckbox(s, name, title, info) {
|
||||
};
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.classList.add("col-right");
|
||||
right.appendChild(input);
|
||||
right.appendChild(label);
|
||||
return appendToContent(info, left, right);
|
||||
return appendToContent(component, left, right);
|
||||
}
|
||||
|
||||
function createSelection(s, name, title, buttons, info) {
|
||||
function create_enum_row(s, component) {
|
||||
// Creates row-element containing dropdown-selection.
|
||||
var name = component.name;
|
||||
var command = component.command;
|
||||
var buttons = component.enum_names;
|
||||
|
||||
var left = createTitle(title, info);
|
||||
var left = createTitle(component);
|
||||
|
||||
var select = document.createElement('select');
|
||||
select.setAttribute("name", name);
|
||||
select.setAttribute("__ctype__", "enum");
|
||||
select.setAttribute("class", "select-params");
|
||||
var select = createParElement(component, 'select', 'select-params');
|
||||
|
||||
select.onfocus = function () {
|
||||
select.setAttribute("oldIndex", select.selectedIndex);
|
||||
select.oldIndex = select.selectedIndex;
|
||||
}
|
||||
|
||||
select.oninput = function () {
|
||||
if (writePermission && title != "device config") {
|
||||
if (writePermission && component.title != "device config") {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + this.value);
|
||||
sendCommand(s, command + " " + this.value);
|
||||
} else {
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
@@ -488,38 +423,37 @@ function createSelection(s, name, title, buttons, info) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + select.value);
|
||||
sendCommand(s, command + " " + select.value);
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
select.value = select.options[select
|
||||
.getAttribute("oldIndex")].value;
|
||||
select.value = select.options[select.oldIndex].value
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
var option = document.createElement('option');
|
||||
option.setAttribute("type", "enum");
|
||||
option.setAttribute("class", "option-params");
|
||||
option.setAttribute("value", buttons[i].value);
|
||||
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.setAttribute("class", "col-right");
|
||||
right.classList.add("col-right");
|
||||
right.appendChild(select);
|
||||
return appendToContent(info, left, right);
|
||||
return appendToContent(component, left, right);
|
||||
}
|
||||
|
||||
function createTitle(title, info) {
|
||||
function createTitle(component) {
|
||||
// Creates left side of row-tag containing title. Title may hold additional
|
||||
// information, which is shown, when title-tag is clicked.
|
||||
|
||||
var left = document.createElement('span');
|
||||
if (info) {
|
||||
left.setAttribute("class", "col-left event-toggle-info");
|
||||
if (component.info) {
|
||||
left.classList.add("col-left", "event-toggle-info");
|
||||
|
||||
left.onclick = function () {
|
||||
var infoBox = left.parentNode.childNodes[0];
|
||||
@@ -530,41 +464,48 @@ function createTitle(title, info) {
|
||||
}
|
||||
}
|
||||
|
||||
left.innerHTML = title + "<sup><b>(i)</b></sup>";
|
||||
left.innerHTML = component.title + "<sup><b>(i)</b></sup>";
|
||||
} else {
|
||||
left.setAttribute("class", "col-left");
|
||||
left.innerHTML = title;
|
||||
left.classList.add("col-left");
|
||||
left.innerHTML = component.title;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
function createInfo(info) {
|
||||
function createParElement(component, tag='span', cls='col-right') {
|
||||
var right = document.createElement(tag);
|
||||
if (cls)
|
||||
right.classList.add(cls);
|
||||
// right.name = is not sufficient, getElementsByName would not work
|
||||
right.setAttribute('name', component.name);
|
||||
right.__ctype__ = component.type;
|
||||
return right;
|
||||
}
|
||||
|
||||
function createInfo(component) {
|
||||
// Creates info-box, which isn't visible by default but can be displayed.
|
||||
|
||||
var infoBox = document.createElement('div');
|
||||
infoBox.setAttribute("class", "info-box");
|
||||
infoBox.classList.add("info-box");
|
||||
|
||||
infoBox.onclick = function () {
|
||||
infoBox.style.display = "none";
|
||||
}
|
||||
|
||||
infoBox.innerHTML = info;
|
||||
infoBox.innerHTML = component.info;
|
||||
return infoBox;
|
||||
}
|
||||
|
||||
function appendToContent(info, left, right) {
|
||||
// Cretees row-tag containing infoBox (not visible by default), left side
|
||||
// (span)
|
||||
// and right side (span).
|
||||
function appendToContent(component, left, right) {
|
||||
// Creates row-tag containing infoBox (not visible by default), left side
|
||||
// (span) and right side (span).
|
||||
|
||||
var row = document.createElement('div');
|
||||
row.setAttribute("class", "row");
|
||||
if (info) {
|
||||
row.appendChild(createInfo(info));
|
||||
row.classList.add("row");
|
||||
if (component.info) {
|
||||
row.appendChild(createInfo(component));
|
||||
}
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
if (arguments[i]) {
|
||||
row.appendChild(arguments[i]);
|
||||
}
|
||||
row.appendChild(left);
|
||||
row.appendChild(right);
|
||||
return row;
|
||||
}
|
||||
@@ -2,31 +2,18 @@
|
||||
// % INIT
|
||||
|
||||
var MAXBLOCK = 4; // max number of blocks
|
||||
|
||||
var elements = []; // grid elements
|
||||
|
||||
var swiper = []; // This array contains main-swiper-Instances.
|
||||
|
||||
var hostPort = ""; // Address and port of static html-file.
|
||||
|
||||
var clientID = ""; // ID given by server when SSE-connection is established.
|
||||
|
||||
var clientTitle = ""; // Contains name of instrument and device.
|
||||
|
||||
var getUpdates = true;
|
||||
|
||||
var getUpdatesGraphics = true;
|
||||
|
||||
var initCommands = [];
|
||||
|
||||
var loadingShown = true;
|
||||
|
||||
var writePermission = false;
|
||||
|
||||
var menuMode = false;
|
||||
|
||||
var panelOn = true;
|
||||
|
||||
var firstState = 0;
|
||||
|
||||
function Settings() {
|
||||
@@ -188,11 +175,11 @@ function toggleHeader() {
|
||||
panelOn = !panelOn;
|
||||
if (panelOn) {
|
||||
header.innerHTML = clientTitle
|
||||
/* header.setAttribute("style", "width: auto;"); */
|
||||
main_panel.setAttribute("style", "display: block;");
|
||||
/* header.style.width = "auto;"; */
|
||||
main_panel.style.display = "block";
|
||||
} else {
|
||||
/* header.setAttribute("style", "width: 30px;"); */
|
||||
main_panel.setAttribute("style", "display: none;");
|
||||
/* header.style.width = "30px"; */
|
||||
main_panel.style.display = "none";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2,14 +2,12 @@
|
||||
// % RESPONSIVITY
|
||||
|
||||
var nColumns = 1; // Viewport is subdivided in nColumns columns.
|
||||
|
||||
var nRows = 1; // Viewport is subdivided in nRows rows.
|
||||
|
||||
var gridCountGraphics = 2; // Number of displayed graphics-swipers.
|
||||
|
||||
var MINWIDTH = 400; // Minimal width of block.
|
||||
|
||||
var MINHEIGHT = 700; // Minimal height of block.
|
||||
let paramSlider = [0,1,2,3]; // the number of the parameter slider to open
|
||||
let prevActiveSlider = 0;
|
||||
|
||||
function createGrid() {
|
||||
// Creates grid-elements. By default only the first one is shown
|
||||
@@ -18,7 +16,7 @@ function createGrid() {
|
||||
var elements = [];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var element = document.createElement('div');
|
||||
element.setAttribute("class", "grid-element");
|
||||
element.classList.add("grid-element");
|
||||
document.getElementById("center").appendChild(element);
|
||||
elements.push(element);
|
||||
}
|
||||
@@ -66,6 +64,8 @@ function adjustGrid() {
|
||||
|| document.body.clientWidth;
|
||||
var height = window.innerHeight || document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
paramSlider = [0,1,2,3];
|
||||
prevActiveSlider = 0;
|
||||
|
||||
switch (nColumns) {
|
||||
case 1:
|
||||
@@ -134,6 +134,8 @@ function adjustGrid() {
|
||||
|
||||
function style(s, width, height) {
|
||||
if (width) {
|
||||
paramSlider[prevActiveSlider] = s;
|
||||
prevActiveSlider = s;
|
||||
elements[s].style.display = "inline-block";
|
||||
elements[s].style.width = width;
|
||||
} else {
|
||||
@@ -145,7 +147,4 @@ function style(s, width, height) {
|
||||
elements[s].style.float = "left";
|
||||
}
|
||||
|
||||
function isTouchDevice() {
|
||||
return !!('ontouchstart' in window)
|
||||
|| !!('msmaxtouchpoints' in window.navigator);
|
||||
};
|
||||
let isTouchDevice = !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);
|
||||
@@ -6,54 +6,63 @@ function insertSwiper(s) {
|
||||
// 'grid-element' s.
|
||||
|
||||
var container = document.createElement('div');
|
||||
container.setAttribute("class", "swiper-container swiper-container-main");
|
||||
container.classList.add("swiper-container", "swiper-container-main");
|
||||
elements[s].appendChild(container);
|
||||
|
||||
var swiperwrapper = document.createElement('div');
|
||||
swiperwrapper.setAttribute("class", "swiper-wrapper swiper-wrapper-main");
|
||||
swiperwrapper.setAttribute("s", s);
|
||||
swiperwrapper.classList.add("swiper-wrapper", "swiper-wrapper-main");
|
||||
swiperwrapper.s = s;
|
||||
container.appendChild(swiperwrapper);
|
||||
|
||||
var paginationWrapper = document.createElement('div');
|
||||
paginationWrapper.setAttribute("class", "swiper-pagination");
|
||||
paginationWrapper.classList.add("swiper-pagination");
|
||||
container.appendChild(paginationWrapper);
|
||||
|
||||
var buttonPrev = document.createElement("div");
|
||||
buttonPrev.setAttribute("class", "swiper-button-prev swiper-button-black");
|
||||
buttonPrev.classList.add("swiper-button-prev", "swiper-button-black");
|
||||
|
||||
var buttonNext = document.createElement("div");
|
||||
buttonNext.setAttribute("class", "swiper-button-next swiper-button-black");
|
||||
buttonNext.classList.add("swiper-button-next", "swiper-button-black");
|
||||
|
||||
var swiper = new Swiper(container, {
|
||||
direction : 'horizontal',
|
||||
pagination: {
|
||||
el: paginationWrapper,
|
||||
clickable: true
|
||||
clickable: true,
|
||||
},
|
||||
watchOverflow: true,
|
||||
spaceBetween : 0,
|
||||
navigation:{
|
||||
prevEl: buttonPrev,
|
||||
nextEl: buttonNext
|
||||
}
|
||||
},
|
||||
noSwiping: true, // this activates the noSwipingClass functionality
|
||||
});
|
||||
//console.log(swiper);
|
||||
|
||||
|
||||
if (!isTouchDevice()) {
|
||||
// Add swiper-button.
|
||||
// the graphics slide will disable swiping (use hide box instead)
|
||||
if (isTouchDevice) {
|
||||
function enableSwiping(allow) {
|
||||
swiper.params.noSwipingClass = allow ? null : "swiper-slide-main";
|
||||
}
|
||||
} else {
|
||||
function enableSwiping(allow) {
|
||||
buttonPrev.style.display = allow ? 'block' : 'none';
|
||||
buttonNext.style.display = allow ? 'block' : 'none';
|
||||
}
|
||||
swiper.params.noSwipingClass = "swiper-slide-main";
|
||||
container.appendChild(buttonPrev);
|
||||
container.appendChild(buttonNext);
|
||||
}
|
||||
|
||||
swiper.enableSwiping = enableSwiping;
|
||||
return swiper;
|
||||
}
|
||||
|
||||
function findSlide(s, type) {
|
||||
var i;
|
||||
for (i = 0; i < swiper[s].slides.length; i++) {
|
||||
if (swiper[s].slides[i].getAttribute("slide-type") === type) {
|
||||
return swiper[s].slides[i];
|
||||
if (swiper[s].slides[i].slideType === type) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -66,66 +75,67 @@ function replaceSlideContent(slide, title, content) {
|
||||
}
|
||||
|
||||
function insertSlide(s, title, type, content) {
|
||||
// Inserts new group to instance s of Swiper.
|
||||
// Inserts new group to instance s of Swiper. return inserted position
|
||||
|
||||
var slide = findSlide(s, type);
|
||||
var isl = findSlide(s, type);
|
||||
var slide = swiper[s].slides[isl];
|
||||
if (slide) { // slide already exists
|
||||
replaceSlideContent(slide, title, content);
|
||||
return
|
||||
return isl;
|
||||
}
|
||||
var panel = document.createElement('div');
|
||||
panel.setAttribute("class", "panel");
|
||||
panel.classList.add("panel");
|
||||
|
||||
titlewrapper = document.createElement('span');
|
||||
titlewrapper.innerHTML = title;
|
||||
panel.appendChild(titlewrapper);
|
||||
/*
|
||||
if (type == "_overview" || type == "main") {
|
||||
//panel.appendChild(createHomeButton(s));
|
||||
} else if (type != "graphics" && type != "_inst_select" && type != "console") {
|
||||
panel.appendChild(createCloseButton(s));
|
||||
}
|
||||
*/
|
||||
|
||||
/*if (type === "graphics") {
|
||||
panel.appendChild(createUpdateButton(s));
|
||||
}*/
|
||||
|
||||
slide = document.createElement('div');
|
||||
slide.setAttribute("class", "swiper-slide swiper-slide-main");
|
||||
slide.classList.add("swiper-slide", "swiper-slide-main");
|
||||
// Store type so it can be found easiely later.
|
||||
slide.setAttribute("slide-type", type);
|
||||
slide.slideType = type;
|
||||
slide.appendChild(panel);
|
||||
slide.appendChild(content);
|
||||
// Graphics-slide is put at mostleft position.
|
||||
if (type == "graphics" || type == "_overview") {
|
||||
// Remove old graphics-slide.
|
||||
/* see above
|
||||
if(swiper[0].slides[0].getAttribute("slide-type") === "graphics"){
|
||||
swiper[0].removeSlide(0);
|
||||
}
|
||||
*/
|
||||
swiper[s].prependSlide(slide);
|
||||
swiper[s].slideTo(0);
|
||||
} else if (type == "console") {
|
||||
swiper[s].appendSlide(slide);
|
||||
return 0;
|
||||
}
|
||||
swiper[s].appendSlide(slide);
|
||||
if (type == "console") {
|
||||
if (s === 3) {
|
||||
// Slide mostright swiper-instance to last position (console)
|
||||
swiper[3].slideNext();
|
||||
}
|
||||
} else {
|
||||
swiper[s].appendSlide(slide);
|
||||
if (swiper[s].slides.length > 1) {
|
||||
var consoleslide = swiper[s].slides[swiper[s].slides.length - 2];
|
||||
if (consoleslide.getAttribute["slide-type"] == "console") {
|
||||
// shift Console-slide to mostright position.
|
||||
swiper[s].removeSlide(swiper[s].slides.length - 2);
|
||||
swiper[s].appendSlide(consoleslide);
|
||||
// Slide to position of new slide
|
||||
swiper[s].slideTo(swiper[s].slides.length - 2);
|
||||
} else {
|
||||
swiper[s].slideTo(swiper[s].slides.length - 1);
|
||||
}
|
||||
return swiper[s].slides.length - 1;
|
||||
}
|
||||
let pos = 0;
|
||||
if (swiper[s].slides.length > 1) {
|
||||
var consoleslide = swiper[s].slides[swiper[s].slides.length - 2];
|
||||
if (consoleslide.slideType == "console") {
|
||||
// shift Console-slide to mostright position.
|
||||
swiper[s].removeSlide(swiper[s].slides.length - 2);
|
||||
swiper[s].appendSlide(consoleslide);
|
||||
// Slide to position of new slide
|
||||
pos = swiper[s].slides.length - 2;
|
||||
} else {
|
||||
pos = swiper[s].slides.length - 1;
|
||||
}
|
||||
}
|
||||
swiper[s].slideTo(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
function createCloseButton(s) {
|
||||
@@ -143,7 +153,7 @@ function createCloseButton(s) {
|
||||
function createUpdateButton(s){
|
||||
// Creates 'span'-element containing update-button (Should be removed later!)
|
||||
var button = document.createElement('span');
|
||||
button.setAttribute("class","interactive toggle-updates-graphics")
|
||||
button.classList.add("interactive", "toggle-updates-graphics")
|
||||
button.onclick = function () {
|
||||
getUpdatesGraphics = ! getUpdatesGraphics;
|
||||
button.innerHTML = "updates = "+getUpdatesGraphics;
|
||||
@@ -162,7 +172,7 @@ function getSlideNames() {
|
||||
var sw = swiper[s];
|
||||
var name = "";
|
||||
if (sw.activeIndex != defaultSlidePos(s)) {
|
||||
name = sw.slides[sw.activeIndex].getAttribute("slide-type");
|
||||
name = sw.slides[sw.activeIndex].slideType;
|
||||
}
|
||||
names.push();
|
||||
}
|
||||
|
||||
+18
-20
@@ -117,31 +117,28 @@ def get_vars(main, time):
|
||||
|
||||
time, = get_abs_time(time)
|
||||
# get last value only
|
||||
curves = main.get_curves(['$vars'], (time, time))
|
||||
for _, value in curves['$vars'].get():
|
||||
for var in value.split():
|
||||
vars = var.split("|")
|
||||
if len(vars) == 1:
|
||||
vars.append("")
|
||||
if len(vars) == 2:
|
||||
vars.append(vars[0])
|
||||
if len(vars) == 3:
|
||||
vars.append("")
|
||||
if len(vars) == 4:
|
||||
vars.append("") # exact flag
|
||||
name, unit, label, color, continuous = vars
|
||||
continuous = int(continuous) if continuous else 0
|
||||
if not unit in result:
|
||||
result[unit] = dict(tag=unit, unit=unit.split("_")[0], curves=Dict())
|
||||
result[unit]["curves"][name] = dict(name=name, label=label, color=color, continuous=continuous)
|
||||
curves = main.get_curve_options((time, time))
|
||||
for key, opts in curves.items():
|
||||
if not opts.get('show', False):
|
||||
continue
|
||||
print(key, opts)
|
||||
opts = dict(name=key, **opts)
|
||||
unit = opts.pop('unit', '*')
|
||||
tag = opts.pop('tag', unit)
|
||||
if not tag in result:
|
||||
result[tag] = dict(tag=tag, unit=unit, curves=Dict())
|
||||
if 'label' not in opts:
|
||||
opts['label'] = opts['name']
|
||||
result[tag]["curves"][key] = opts
|
||||
|
||||
for unit, curvegroup in result.items():
|
||||
# determine colors
|
||||
for _, curvegroup in result.items():
|
||||
color_set = set()
|
||||
auto_curves = []
|
||||
curve_list = list(curvegroup["curves"].values())
|
||||
curvegroup['curves'] = curve_list
|
||||
for curve in curve_list:
|
||||
col = curve["color"].strip()
|
||||
col = curve.get("color", '').strip()
|
||||
c = ColorMap.to_code(col)
|
||||
if c < 0:
|
||||
valid = ColorMap.check_hex(col)
|
||||
@@ -166,8 +163,9 @@ def get_vars(main, time):
|
||||
|
||||
def get_curves(main, keys, timerange, cut_begin=True):
|
||||
curves = main.get_curves(keys, get_abs_time(*timerange), maxpoints=500, cut_begin=cut_begin)
|
||||
opts = main.get_curve_options(timerange, keys)
|
||||
#if 'tt:target' in curves:
|
||||
# print('---')
|
||||
# print(curves['tt:target'].fmtm())
|
||||
# print('TT', curves['tt:target'].for_json()[-5:])
|
||||
return {k: c.for_json() for k, c in curves.items()}
|
||||
return {k: c.for_json(opts.get(k, {}).get('period', 0)) for k, c in curves.items()}
|
||||
+20
-14
@@ -25,8 +25,8 @@ import circularlog
|
||||
import os
|
||||
import signal
|
||||
from histgraph import get_vars, get_curves, get_abs_time
|
||||
from histreader import MainCache
|
||||
from frappyreader import FrappyReader
|
||||
from histreader.histreader import MainCache
|
||||
from histreader.frappyreader import FrappyReader
|
||||
|
||||
try: import simplejson as json
|
||||
except ImportError: import json
|
||||
@@ -668,7 +668,7 @@ class DummyClient(SeaGraph):
|
||||
self.syncreply = []
|
||||
SeaGraph.__init__(self)
|
||||
|
||||
def cmd_reply(self, command, replytype, tmo=5):
|
||||
def cmd_reply(self, command, replytype=None, tmo=5):
|
||||
self.linesocket.send_line(json.dumps(command))
|
||||
t = 0
|
||||
while True:
|
||||
@@ -689,7 +689,7 @@ class DummyClient(SeaGraph):
|
||||
raise Exception("timeout")
|
||||
gevent.sleep(0.1)
|
||||
t += 0.1
|
||||
if msg.type != replytype:
|
||||
if replytype and msg.type != replytype:
|
||||
logging.error('REPLY MISMATCH %s %s <> %s', command, replytype, msg.type)
|
||||
return msg
|
||||
|
||||
@@ -788,8 +788,14 @@ def SecopEncode(cmd, par=None, value=None):
|
||||
def convert_par(module, name, par):
|
||||
result = dict(type='input', name=module+":"+name, title=name)
|
||||
if par.get('readonly', True):
|
||||
result['type']='rdonly'
|
||||
#print result
|
||||
result['type'] = 'rdonly'
|
||||
else:
|
||||
result['command'] = 'change %s:%s' % (module, name)
|
||||
if par['datainfo']['type'] == 'enum':
|
||||
result['enum_names'] = [dict(title=k, value=v) for k, v in par['datainfo']['members'].items()]
|
||||
result['type'] = 'enum'
|
||||
elif par['datainfo']['type'] == 'bool':
|
||||
result['type'] = 'checkbox'
|
||||
return result
|
||||
|
||||
|
||||
@@ -799,7 +805,8 @@ def convert_event(messages):
|
||||
updates = []
|
||||
for msg in messages:
|
||||
if msg.type == 'update':
|
||||
updates.append(dict(name=msg.par, value=str(msg.value[0])))
|
||||
updates.append(dict(name=msg.par, value=msg.value[0]))
|
||||
# updates.append(dict(name=msg.par, value=str(msg.value[0])))
|
||||
return [dict(type='update', updates=updates)]
|
||||
|
||||
|
||||
@@ -822,7 +829,7 @@ class SecopClient(SeaGraph):
|
||||
self.idn = idn.value
|
||||
self.description = self.cmd_reply("describe", "describing").value
|
||||
|
||||
def cmd_reply(self, command, replytype, tmo=5):
|
||||
def cmd_reply(self, command, replytype=None, tmo=5):
|
||||
logging.info('COMMAND %r', command)
|
||||
self.replytype = replytype
|
||||
if self.out: self.out.write(">"+command+"\n")
|
||||
@@ -855,7 +862,7 @@ class SecopClient(SeaGraph):
|
||||
logging.info('REPLY %r', msg)
|
||||
if msg.type.startswith('error_'):
|
||||
return {}
|
||||
if not replytype.startswith(msg.type):
|
||||
if replytype and not replytype.startswith(msg.type):
|
||||
logging.error('REPLY MISMATCH %s <> %s', replytype, repr(msg))
|
||||
self.replytype = ""
|
||||
return msg
|
||||
@@ -872,7 +879,7 @@ class SecopClient(SeaGraph):
|
||||
return dict(type='draw', path='main', title='modules', components=components)
|
||||
else:
|
||||
module = self.description['modules'][path]
|
||||
parameters = module["accessibles"]
|
||||
parameters = dict(module["accessibles"])
|
||||
components = []
|
||||
for name in SecopClient.skip_par:
|
||||
if name in parameters:
|
||||
@@ -900,8 +907,7 @@ class SecopClient(SeaGraph):
|
||||
def w_sendcommand(self, command):
|
||||
if not command:
|
||||
return dict(type='accept-command')
|
||||
cmd = "change " + command
|
||||
self.cmd_reply(cmd, 'changed ' + command.split(' ')[0])
|
||||
self.cmd_reply(command)
|
||||
return dict(type='accept-command')
|
||||
|
||||
def poll(self):
|
||||
@@ -1006,8 +1012,8 @@ if __name__ == '__main__':
|
||||
|
||||
instrument_config = instrument_list[inst_name]
|
||||
|
||||
frd = FrappyReader('/Users/zolliker/frappyhist/%s' % inst_name, gevent=gevent)
|
||||
main_cache = MainCache('/Users/zolliker/frappyhist/%s_hist' % inst_name, frd, gevent=gevent)
|
||||
frd = FrappyReader('/Users/zolliker/frappyhist/%s' % inst_name)
|
||||
main_cache = MainCache('/Users/zolliker/frappyhist/%s_hist' % inst_name, frd, spawn_worker=False)
|
||||
|
||||
# logging.basicConfig(filename=inst_name+".log", filemode='w', level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
|
||||
|
||||
Reference in new issue
Block a user