--------------------------------------------------------------------------------
problems:
--------------------------------------------------------------------------------
working on:
--------------------------------------------------------------------------------
to do:
-- simplify niceScale() and niceScaleFitting() after octave m-files scaletick_*.m
-- note that real2eng() can take care of harmonisation for the display of a series of numbers
-- remove formatReal() and formatRealSplit() in favour of real2eng()
or: simplify input/output records so that formatReal() output directly corresponds with output of real2eng()
-- improve accordingly formatRealOrDatetime()
-- easy boolean to switch on/off automatic selection of linestyles and/or markers (in a default ordre)
data["fig"][ifig]["tab"][itab][field]
data["fig"][ifig][field] ifnot:
data[field] ifnot:
defaults[field] = 0 or 1;
field = "autolinestyle" or "automarkerstyle"
implement this in hplot.m too!
-- possible simplification:
-- restrict "commondatakey", "commondatacolumn" and "datetimecommon" only for common data which is not on x axis
-- introduce "commondataonxaxis" (instead of ...commondatakey = "=xdata") when x axis data is also common data
-- ensure null, NaN/false for x data points in js function plot()
bisnan = ( isNaN(bx) || isNaN(by) || (bx === false) || (by === false) )
bisnull = ( (bx === null) || (by === null) )
-- apply simplifications from hplot() used for autocolour etc.
-- filled x data & empty y data --> ensure that nothing is plotted (apart from title)
-- implement markernumber
-- fast read of data by reading it as json by a json string read function: object = JSON.parse(code)
-- note that NaN, Inf are not allowed, but null, false and true are!
-- no single quotes are allowed, only "
==> line break indicated by Inf in octave, null in js
ignoring indicated by NaN in octave, NaN or false in js
-- button panel
-- preference zoom, given by data["fig"][ifig]["xlimpref"] = [1,2] and data["fig"][ifig]["ylimpref"] = [2,3]
-- switch to put display values in legend off
-- fast write of matrices hplot_to_html()
-- hplot_to_html(p1,p2,...) in p2.matrix1 = [...]
-- or: p.fig{2}.matrix1 = [...]
p.fig{2}.ismatrix = {"matrix1"}
-- or: p.fig{3}.matrix1__m = [...] <-- special suffix is kept!
-- or: use switch and ismatrix() in var2json() and print matrix at once without indentation!
-- rename value2json()
-- atg plot
-- data["fig"][ifig]["overlay"] = "atl" (atg) --> just extra graphical lines (overlay) and fields (underlay !)
-- data["fig"][ifig]["atl_count"] = true
--> table next to figure:
D- C- B A C+ D+ outside D C B A
10 ser0 all
%
10 ser0 select
%
--> calculation at init: data["fig"][ifig]["_atl_count"] = [1, 2, 3;...] --> reference to fields in graph per series
-- mollier
-- add rho lines
-- print (X,F,H,...) values at mouse pointer below legend
-- mouse pointer -> closest based on sqrt( (delta x)^2 + (delta y)^2 )
--> may cause problems if one realy wants to find by x first!
==> extra checkbox (take delta y into account, or not) in button panel
-- legend:
-- colspan for first two rows: <th colspan="2">headline 1</th>
-- check and improve markerskip
-- implement second transformation: from converted data axis system and units
to projected data axis system and units
(xp,yp) := projectionfunction(xc,yc)
--> log-log, ln-ln, lin-log, etc.
-- visibility of series does not affect y axis range --> as an option !
-- visibility does affect drawing of pointer circle
-- pointed x axis value --> nearest x axis value --> show corresponding y axis value
problem: sometimes line goes flat/horizontal
but: -- better: nearest two x axis values (before _and_ after pointed x axis value)
to determine y axis range and better display
-- interpolation?
-- add new possible value for xlim1 in scaleFigures(igrp,ifig1,xlim1,xlim2)
if isNaN(xlim1) --> all data
if xlim1 == null --> redraw for actual/previously xlim1,xlim2 values
--> practical when series are set to visible again
-- prepareFigureTable(): is a check for same address when commononxaxis == true needed?
if so, add it.
-- move defaults to data["_defaults"] ?
-- apply simplifications from hplot.m used for getdata(), getdataaddress() etc.
--------------------------------------------------------------------------------
there are three types of figure groups:
-1- figures with xdatakey="c", ydatakey="y", commondatakey="c", commononxaxis=true, commongiven=true
==> x axis range change influences all figures in the same figure group
data["_grp"][igrp]["csorted"]
data["_grp"][igrp]["ysorted"]
data["_grp"][igrp]["xminmax"]
data["fig"][ifig]["_yminmax"]
figures with xdatakey="x", ydatakey="y", commondatakey="c", commononxaxis=false, commongiven=true
==> x axis range change at this figure has no effect on other figures in the figure group
==> x axis range change at another figure of c,y-type influences displayd points
data["fig"][ifig]["_xminmax"]
data["fig"][ifig]["_yminmax"]
also series with xdatakey="x", ydatakey="y", commondatakey="", commononxaxis=false, commongiven=false
-2- figures with xdatakey="c", ydatakey="y", commondatakey="c", commononxaxis=true, commongiven=true
==> x axis range change influences all figures in the same figure group
data["_grp"][igrp]["csorted"]
data["_grp"][igrp]["ysorted"]
data["_grp"][igrp]["xminmax"]
data["fig"][ifig]["_yminmax"]
also series with xdatakey="x", ydatakey="y", commondatakey="", commononxaxis=false, commongiven=false
-3- figure with xdatakey="x", ydatakey="y", commondatakey="", commononxaxis=false, commongiven=false
==> figure group contains only one figure !
data["fig"][ifig]["_xminmax"]
data["fig"][ifig]["_yminmax"]
--------------------------------------------------------------------------------
structure of global variable data:
data["fig"][ifig]["title"] = "<b>abc</b>";
-- string of html code
-- if not given, defaults["title"] = ""
data["fig"][ifig]["caption"] = "<b>abc</b>";
-- string of html code
-- if not given, defaults["caption"] = ""
data["fig"][ifig]["group"] = "abc";
-- string
-- if not given, defaults["group"] = ""
-- if empty string, the figure constitues its own group
data["fig"][ifig]["xdatakey"] = "x"
data["fig"][ifig]["tab"][itab]["xdatakey"] = "x"
-- string
-- if not given, defaults["xdatakey"] = "x"
data["fig"][ifig]["ydatakey"] = "y"
data["fig"][ifig]["tab"][itab]["ydatakey"] = "x"
-- string
-- if not given, defaults["ydatakey"] = "y"
data["fig"][ifig]["commondatakey"] = "c"
data["fig"][ifig]["tab"][itab]["commondatakey"] = "c"
-- string
-- if "=xdata", data....["xdatakey"] and data....["xdatacolumn"] are taken instead
-- if not given, defaults["commondatakey"] = ""
data["fig"][ifig]["datetimeonxaxis"] = true/false
data["fig"][ifig]["datetimecommon"] = true/false
data["fig"][ifig]["tab"][itab]["datetimecommon"] = true/false
-- boolean
-- false by default
-- must be set to true, if x axis or common data are in ms since 1970-01-01 00:00:00.0000 (unix epoch)
-- may be set to true, if x axis or common data are given by separate columns for year, month etc.
-- in the latter case, it is needed to input:
data[...]["xdatacolumn"] = { ye: icol, mo: icol, ... }
or
data[...]["commondatacolumn"] = { ye: icol, mo: icol, ... }
data["fig"][ifig]["xdataconversion"] = ""
data["fig"][ifig]["tab"][itab]["xdataconversion"] = ""
-- string with values "" or "temp<temp", ...
-- if not given, defaults["xdataconversion"] = ""
data["fig"][ifig]["ydataconversion"] = ""
data["fig"][ifig]["tab"][itab]["ydataconversion"] = ""
-- string with values "" or "hum<rehum", ...
-- if not given, defaults["ydataconversion"] = ""
data["fig"][ifig]["xaxisprojection"] = "lin"
-- string with values "" or "lin"
-- if not given, defaults["xaxisprojection"] = "lin"
data["fig"][ifig]["yaxisprojection"] = "lin"
-- string with values '' or "lin"
-- if not given, defaults["yaxisprojection"] = "lin"
data["fig"][ifig]["rotated"] = true/false
-- boolean
-- if not given, defaults["rotated"] = false
data[j] = [ [...], [...], ...]
data["fig"][ifig][j] = [ [...], [...], ...]
data["fig"][ifig]["tab"][itab][j] = [ [...], [...], ...]
-- needed
-- two-dimensional array with data for x axis, y axis and common
-- let j = data["fig"][ifig]["xdatakey"] or data["fig"][ifig]["ydatakey"] or data["fig"][ifig]["commondatakey"], respectively
-- searched for in priority
data["fig"][ifig]["tab"][itab]["legend"] = [ "abc", "abc", ...];
-- array of strings
data["fig"][ifig]["tab"][itab]["style"] = [ {...}, {...}, ...];
-- array of records with (optional) fields "colour", "line", "linewidth", "isstep", "marker", "markerskip", "markerscale"
data["xdatacolumn"] = [ 0 ];
data["commondatacolumn"] = [ 0 ];
data["fig"][ifig]["xdatacolumn"] = [ 0 ];
data["fig"][ifig]["commondatacolumn"] = [ 0 ];
data["fig"][ifig]["tab"][itab]["xdatacolumn"] = [ 0 ];
data["fig"][ifig]["tab"][itab]["ydatacolumn"] = [ 0 ];
data["fig"][ifig]["tab"][itab]["commondatacolumn"] = [ 0 ];
-- optional (only needed when x axis, y axis and/or common data are all in the same data array)
-- array of indices for refering to column(s) in the data array contained in the respective field j
-- searched for in priority
data["xdatacolumn"] = { ye: icol, mo: icol, da: icol, ho: icol, mi: icol, se: icol, ms: icol };
data["commondatacolumn"] = { ye: icol, mo: icol, da: icol, ho: icol, mi: icol, se: icol, ms: icol };
data["fig"][ifig]["xdatacolumn"] = { ye: icol, mo: icol, ... };
data["fig"][ifig]["commondatacolumn"] = { ye: icol, mo: icol, ... };
data["fig"][ifig]["tab"][itab]["xdatacolumn"] = { ye: icol, mo: icol, ... };
data["fig"][ifig]["tab"][itab]["commondatacolumn"] = { ye: icol, mo: icol, ... };
-- needed if x axis data or common data are given by separate columns for year, month etc.
-- if icol is an integer number, the value of the date-time element will found in column icol
-- if icol is a string, the number obtained by parsing the string will be filled in as fixed value for the respective date-time element
--------------------------------------------------------------------------------
window.onload = function()
set global variable use_svg_symbol
for ifig ---> ensureSvgElem(ifig)
for ifig ---> prepareFigure(ifig)
for ifig ---> drawFigure(ifig)
for igrp ---> analyseSeries(igrp)
drawSeries(igrp)
for igrp ---> scaleFigures(igrp,-1,NaN,NaN)
--------------------------------------------------------------------------------
function prepareFigure(ifig)
setting:
data["fig"][ifig]["_numero"] = numero;
data["fig"][ifig]["_special"] = special;
data["fig"][ifig]["_air"] = airprop;
data["fig"][ifig]["_xaxisprojection"] = xaxisprojection;
data["fig"][ifig]["_yaxisprojection"] = yaxisprojection;
data["fig"][ifig]["_group"] = group;
data["fig"][ifig]["_igrp"] = igrp;
data["fig"][ifig]["_xlabel"] = getdata(ifig,-1,["xlabel"]).value;
data["fig"][ifig]["_ylabel"] = getdata(ifig,-1,["ylabel"]).value;
data["fig"][ifig]["_xunit"] = getdata(ifig,-1,["xunit"]).value;
data["fig"][ifig]["_yunit"] = getdata(ifig,-1,["yunit"]).value;
for itab --> prepareFigureTable(ifig,itab)
--------------------------------------------------------------------------------
function prepareFigureTable(ifig,itab)
setting:
data["fig"][ifig]["_commononxaxis"] = commononxaxis;
data["fig"][ifig]["_datetimeonxaxis"] = datetimeonxaxis;
data["fig"][ifig]["_datetimecommon"] = datetimecommon;
data["_iserallcur"]
data["_grp"][igrp]["isergrpcur"]
data["fig"][ifig]["_iserfigcur"]
data["fig"][ifig]["_isergrp"].push( isergrp );
data["_grp"][igrp]["figures"] = pushunique(data["_grp"][igrp]["figures"],ifig);
if (dataconversion["psychro"] == true) {
....
dataconversion_psychro(x,icolx,y,icoly,dataconversion["xy"],Pb,Pbdatacolumn,ifig,iserfigs[icol]);
....
}
data["_grp"][igrp]["series"].push({
igrp: igrp,
ifig: ifig,
itab: itab,
icolx: xdatacolumn[0],
icoly: ydatacolumn[icol],
icolc: commondatacolumn[0],
iserfig: iserfigs[icol],
isergrp: isergrp,
iserall: iserall,
xdatakey: xdatakey,
ydatakey: ydatakey,
commondatakey: commondatakey,
commononxaxis: commononxaxis,
commongiven: commongiven,
datetimeonxaxis: datetimeonxaxis,
datetimecommon: datetimecommon,
xdataconversion: xdataconversion,
ydataconversion: ydataconversion,
xaxisprojection: xaxisprojection,
yaxisprojection: yaxisprojection,
xaddress: xaddress.slice(),
yaddress: yaddress.slice(),
caddress: caddress.slice(),
Pbaddress: Pbaddress,
Pbdatacolumn: Pbdatacolumn,
legend: legends[icol],
colour: styles[icol]["colour"],
line: styles[icol]["line"],
linewidth: styles[icol]["linewidth"],
isstep: styles[icol]["isstep"],
marker: styles[icol]["marker"],
markerskip: styles[icol]["markerskip"],
markerscale: styles[icol]["markerscale"],
markerdefid: "", // filled in in drawSeries(igrp) only if needed
displayed: true
});
--------------------------------------------------------------------------------
function drawFigure(ifig)
setting:
data["fig"][ifig]["_rotated"]
data["fig"][ifig]["_axisbox"] = { x : axisboxleftmargin,
y : axisboxtopmargin,
width : axisboxwidth,
height : axisboxheight,
};
data["fig"][ifig]["_spaces"]
data["fig"][ifig]["_width"]
data["fig"][ifig]["_height"]
data["fig"][ifig]["_graphictransform"]
data["fig"][ifig]["_axistransform"]
data["fig"][ifig]["_xthreshold"]
data["fig"][ifig]["_veil"]
data["fig"][ifig]["_seriespointer"]
data["fig"][ifig]["_xaxis"]
data["fig"][ifig]["_yaxis"]
data["fig"][ifig]["_legend"]
data["fig"][ifig]["_Faxis"]
data["fig"][ifig]["_Haxis"]
creating
-- definition group
-- clip-path
-- figure background rectangle
-- axis background rectangle
-- axis-clippath group
-- axis-transform group
-- x/y-axis-grid groups
-- x/y-axis-tick-text groups
-- dummy tick text group (with dummy texts)
-- data["fig"][ifig]["_axisticktextboxsizes"]
-- x/y axis labels
-- veil
-- mouse pointer
-- mouse event object
-- first two rows in the legend
-- buttons
print the title and caption texts
setSpacing(ifig)
--------------------------------------------------------------------------------
function plot(seriesgroup,series,clim1,clim2,graphictransform)
--------------------------------------------------------------------------------
function analyseSeries(igrp)
for isergrp
setting:
-- if data["fig"][ifig]["_commononxaxis"] == true:
data["_grp"][igrp]["csorted"] = c;
data["_grp"][igrp]["ysorted"] = y;
data["_grp"][igrp]["xminmax"] = xminmax;
-- if data["fig"][ifig]["_commononxaxis"] == false:
data["fig"][ifig]["_xminmax"] = xminmax;
-- data["fig"][ifig]["_yminmax"] = yminmax;
for ifig
setting: data["fig"][ifig]["_graphictransformation"]
--------------------------------------------------------------------------------
function drawSeries(igrp)
for isergrp
create marker definition
draw lines and markers: plot(serieslinegroup,seriesmarkergroup,series,NaN,NaN,graphictransform);
draw (invisible) series pointers
print legend
for ifig
add buttons for view periods if date-time on x axis
--------------------------------------------------------------------------------
function scaleFigures(igrp,ifig1,xlim1,xlim2)
/*
-- when x axis value range is given at ("calling") figure ifig1:
-- the range must be implemented to the x axes of every
figure (of type "c,y") within the group
-- to which ifig1 belongs and
-- for which the x axis is common (commononxaxis == true).
-- the range must be implemented to the data points of every
figure (of type "x,y,c") within the group
-- to which ifig1 belongs and
-- for which the x axis is not common (commononxaxis == false
&& commongiven == true).
-- when x axis value range is given with ifig1=-1, so for the whole figure group:
-- for all figures within the figure group
for which the x axis is common (commononxaxis == true):
-- the range is found by all x axis data together
-- the range is implemented for all concerning figures
-- for each figure within the figure group
for which the x axis is not common (commononxaxis == false):
-- the range is found by the x axis data of the concerning figure
-- the range is implemented for of the concerning figure
*/
// it is called within:
// -- window.onload()
// --> for igrp
// scaleFigures(igrp,-1,NaN,NaN)
// -- zoomExtentsFigures(ifig0)
// --> for igrp
// scaleFigures(igrp,-1,NaN,NaN)
// -- onMouseUp(evt,ifig)
// --> scaleFigures(data["fig"][ifig]["_igrp"],ifig,x1,x2);
for ifig
select y by given x1 and x2
scaleSeries(igrp,ifig,xminmaxwin,yminmaxwin)
--------------------------------------------------------------------------------
function scaleFigurey(igrp,ifig,ylim1,ylim2) {
scaleSeries(igrp,ifig,xminmaxwin,yminmaxwin)
--------------------------------------------------------------------------------
function scaleSeries(igrp,ifig,xminmaxwin,yminmaxwin)
calculate axis transformation
draw grid lines
print tick texts
rescale markers
drawPsychro(ifig)
setSpacing(ifig)
--------------------------------------------------------------------------------
function drawPsychro(ifig)
plot F and H grid lines and tick texts
add checkboxes for visibility of F and H axes
--------------------------------------------------------------------------------
function printvaluesFigures(igrp,ifig1,xc,yc)
// it is called within:
// -- zoomExtentsFigures(ifig0)
// --> for igrp
// printvaluesFigures(igrp,-1,NaN,NaN)
// -- onMouseUp(evt,ifig)
// --> if mouseDownStart.line
// printvaluesFigures(data["fig"][ifig]["_igrp"],ifig,(x1+x2)/2,(y1+y2)/2)
// else
// for igrp
// printvaluesFigures(igrp,-1,NaN,NaN)
for ifig
find the x and y values closest to xc
write x axis value to element with id=name + ":legend:x:left/right:ser" + String(igrp) + "," + String(isergrp[iiser])
write y axis value to element with id=name + ":legend:y:left/right:ser" + String(igrp) + "," + String(isergrp[iiser])
set series pointers
--------------------------------------------------------------------------------
function zoomExtentsFigures(ifig0)
unset_mouseDownStart()
for iigrp
igrp = groups[iigrp];
set the veil of all figures in group to total transparency
make visible all series in the figure group
scaleFigures(igrp,-1,NaN,NaN)
printvaluesFigures(igrp,-1,NaN,NaN)
--------------------------------------------------------------------------------
function changeAxisVisibility(visible,axis,ifig)
--------------------------------------------------------------------------------
function toggleAxisVisibility(checkbox,axis,ifig)
--> changeAxisVisibility(checked,axis,ifig);
--------------------------------------------------------------------------------
function changeVisibility(visible,igrp,isergrp)
--> changeVisibility(visible,igrp,isergrp[iiser]);
--> checkbox = document.getElementById(name + ":legend:visibility:ser" + String(igrp) + "," + String(isergrp[iiser]));
checkbox.checked = visible;
--------------------------------------------------------------------------------
function toggleVisibility(checkbox,igrp,isergrp)
--> changeVisibility(visible,igrp,isergrp)
--------------------------------------------------------------------------------
function setVisibilityFigure(ifig,visible)
--------------------------------------------------------------------------------
function retrieveMouseCoord(evt,svg)
--------------------------------------------------------------------------------
function mouseCoordToFigureCoord(xm,ym,ifig)
--------------------------------------------------------------------------------
function figureCoordToDataCoord(xf,yf,ifig)
--------------------------------------------------------------------------------
function unset_mouseDownStart()
--------------------------------------------------------------------------------
function set_mouseDownStart(mousecoord,ifig)
--------------------------------------------------------------------------------
function drawVeil(ifig,name,xf1,xf2)
--------------------------------------------------------------------------------
function onMouseEnter(evt,ifig)
unset_mouseDownStart()
--------------------------------------------------------------------------------
function onMouseMove(evt,ifig)
if ! isNaN(mouseDownStart.xm)
drawVeil(ifig,name,mouseDownStart.xf,actualMouseCoordf.x)
--------------------------------------------------------------------------------
function onMouseDown(evt,ifig)
if isNaN(mouseDownStart.xm)
set_mouseDownStart(actualMouseCoordm,ifig)
drawVeil(ifig,name,mouseDownStart.xf,mouseDownStart.xf)
--------------------------------------------------------------------------------
function onMouseUp(evt,ifig)
if (actualMouseCoordf.inaxisrectangle)
if (mouseDownStart.line)
printvaluesFigures(data["fig"][ifig]["_igrp"],ifig,(x1+x2)/2,(y1+y2)/2)
else
set the veil to total transparency
scaleFigures(data["fig"][ifig]["_igrp"],ifig,x1,x2)
printvaluesFigures(data["fig"][ifig]["_igrp"],-1,NaN,NaN)
unset_mouseDownStart()
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
notes & do-not-forget:
-- it is impossible to refer to a css class within an other css class definition, or extend one css class by another one !
but class definitions may be disperged, e.g.:
.klasse { background-color: yellow; }
.klasse { color: red; border: 2px solid black; }
.klasse { font-family: sans-serif;}
-- https://www.w3.org/TR/SVGTiny12/ --> no markers
https://www.w3.org/TR/SVG11/
-- complete use of option line markers:
-- note: https://www.w3.org/TR/svg-markers/
marker-segment (= marker inbetween two points on path)
marker-pattern (= marker along the path at fixed distances)
-- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
new Date(ms_since_19700101);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
Date.prototype.toISOString()
Converts a date to a string following the ISO 8601 Extended Format.
Date.prototype.toTimeString()
Returns the "time" portion of the Date as a human-readable string.
Date.prototype.valueOf()
Returns the primitive value of a Date object. Overrides the Object.prototype.valueOf() method.
Date.prototype.setTime()
Sets the Date object to the time represented by a number of milliseconds since January 1, 1970, 00:00:00 UTC, allowing for negative numbers for times prior.
dt = new Date(2019,06,07,15,32,00,0)
>> Date 2019-07-07T13:32:00.000Z // time shift CET -> UTC
dt = Date.UTC(2019,06,07,15,32,00,0)
>> 1562513520000
new Date(dt)
>> Date 2019-07-07T15:32:00.000Z // no time shift
a = new Date(dt)
>> Date 2019-07-07T15:32:00.000Z
a.toISOString()
>> "2019-07-07T15:32:00.000Z"
-- <use xlink:href="#..."...> is not accepted, but the href attribute is accepted.
--> perhaps xlink:href attribute is accepted for
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" ...>
--> which is correct notation?
-- https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
Deprecated since SVG 2
SVG 2 removed the need for the xlink namespace, so instead of xlink:href you should use href.
-- Contrary to Firefox, Chrome does not accept (i.e. in Chrome, the following has no tranformation effect at all):
<symbol ... transform="....">
...
</symbol>
But the following has the expected transformation effect in Chrome (and Firefox):
<symbol ... >
<g transform="....">
...
</g>
</symbol>
--------------------------------------------------------------------------------