Visualisierungsmodul für SuperX http://www.superx-projekt.de/doku/viz_modul/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

2322 lines
65 KiB

/*
function chartSkeleton(nr,
title,
subtitle,
dimension1Fldname,
dimension1Caption,
hasDimension2,
dimension2Fldname,
dimension2Caption,
measure1Fldname,
measure1Caption,
hasMeasure2,
measure2Fldname,
measure2Caption
)
{
this.nr=nr;
this.title=title;
this.subtitle=subtitle;
this.dimension1Fldname=dimension1Fldname;
this.dimension1Caption=dimension1Caption;
this.dimension2Fldname=dimension2Fldname;
this.dimension2Caption=dimension2Caption;
this.measure1Fldname=measure1Fldname;
this.measure1Caption=measure1Caption;
this.measure2Fldname=measure2Fldname;
this.measure2Caption=measure2Caption;
this.hasDimension2 = function () {
if(dimension2Fldname && dimension2Fldname !="")
return true;
else
return false;
}
}*/
function d3dataRow(nr,dimension1,dimension2,measure1 )
{
this.nr=nr;
this.dimension1=dimension1;
this.dimension2=dimension2;
this.measure1=measure1;
}
function commonChartProperty(name,
caption,
isMandatory,
inputType,
staticValues,
range_from,
range_to,
defaultValue,
propUnit,
explanation,
groupCaption,
groupUniquename,
rendererUniquename,
groupVariableName,
variableName,
propValueType,
isGeneric
)
{
this.name=name;
this.caption=caption;
this.staticValues=staticValues;
this.range_from=range_from;
this.range_to=range_from;
this.isMandatory=isMandatory;
this.inputType=inputType;
this.defaultValue=defaultValue;
this.propUnit=propUnit;
this.explanation=explanation;
this.groupCaption=groupCaption;
this.groupUniquename=groupUniquename;
this.rendererUniquename=rendererUniquename;
this.groupVariableName=groupVariableName;
this.variableName=variableName;
this.propValueType=propValueType;
this.isGeneric=isGeneric;
this.getValueResultset = function () {
var valueOptions=[];
var optionCounter=0;
var staticValueArray = staticValues.split(/\|/);
for(var j=0;j < staticValueArray.length;j++)
{
var isDefault=false;
if(staticValueArray[j])
{
if(staticValueArray[j]==this.defaultValue)
isDefault=true;
var o=new selectionPropertyValue(optionCounter,staticValueArray[j],staticValueArray[j],isDefault);
valueOptions[optionCounter]=o;
optionCounter++;
}
}
return valueOptions;
}
}
function commonChartPropertyGroup(caption,groupUniquename,groupVariableName)
{
this.caption=caption;
this.groupUniquename=groupUniquename;
this.groupVariableName=groupVariableName;
}
function renderEChart(chartCode,chartDiv,ergebniselementOrdnr)
{
/*obsolete*/
// Initialize the echarts instance based on the prepared dom
var myChart = echarts.init(document.getElementById(chartDiv),null, { renderer: 'svg' });
var datasetSourceRow=new Array();
var datasetSourceCol=new Array();
//first header row:
var columnCount=rsColumnMetaData[ergebniselementOrdnr].length;
var rowCount=rs[ergebniselementOrdnr].length;
datasetSourceCol=['Fakultät (Schlüssel)','Fakultät','Anzahl der Studierenden','Anteil der Studierenden (in %)'];
datasetSourceRow.push(datasetSourceCol);
//now the data:
for(var i=0;i < rowCount;i++)
{
var datasetSourceCol=new Array();
datasetSourceCol.push(rs[ergebniselementOrdnr][i].dim_studiengang_fb);
datasetSourceCol.push(rs[ergebniselementOrdnr][i].dim_studiengang_fb_str);
datasetSourceCol.push(rs[ergebniselementOrdnr][i].summe);
datasetSourceCol.push(rs[ergebniselementOrdnr][i].anteil);
datasetSourceRow.push(datasetSourceCol);
}
// Specify the configuration items and data for the chart
var datasetObj={dataset: {
source: datasetSourceRow
}
};
//var chartCodeObj = JSON.parse(chartCode);
let optionsObj = {
...datasetObj,
...chartCode
};
// Display the chart using the configuration items and data just specified.
myChart.setOption(optionsObj);
}
function openModalCardDetail(ergebniselementOrdnr)
{
var myModalCard=document.getElementById("modalCardDetail"+ergebniselementOrdnr);
myModalCard.classList.add('is-active');
renderEChart("modalCardDetailImage"+ergebniselementOrdnr,ergebniselementOrdnr);
}
function fillEchartsDataSet(myRs,myRsMetaData,currentChartModel)
{
var dataset =new Array();
var chartType=currentChartModel.chartElements[0].vizTypeUniquename;
//Identify dimensions and measures:
switch (chartType) {
case "echarts_pie":
var measure1Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","measure1");
var dimension1Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","dimension1");
dataset=fillEchartsDataSetNameValue(myRs,myRsMetaData,dimension1Fldname,measure1Fldname);
break;
case "echarts_bar_y_stack":
//TODO klappt nich tnicht)
var measure1Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","measure1");
var dimension1Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","dimension1");
var dimension2Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","dimension2");
dataset=fillEchartsDataSetCrosstab(myRs,myRsMetaData,dimension1Fldname,dimension2Fldname,measure1Fldname);
break;
default:
dataset=fillEchartsDataSetSimpleCopy(myRs,myRsMetaData);
break;
}
return dataset;
}
function fillEchartsDataSetSimpleCopy(myRs,myRsMetaData)
{
var myDimensions=[];
var mySource=[];
myRsMetaData.forEach((row) => {
for (var col in row) {
console.log(col +"-"+row[col]);
if(col=="colname" && row[col])
{
myDimensions.push(row[col]);
}
}
});
var rowcount=myRs.length;
var rownr=1;
console.log("Zeilenanzahl " +rowcount);
myRs.forEach((row) => {
mySource.push(row);
rownr++;
}
);
//TODO:Sorting and filtering
return {dimensions:myDimensions, source: mySource };
}
function fillEchartsDataSetCrosstab(myRs,myRsMetaData,dimension1Fldname,dimension2Fldname,measure1Fldname)
{
//TODO, klappt noch nicht
var datasetSourceRow=new Array();
var datasetSourceCol=new Array();
var columnCount=myRsMetaData.length;
var rowCount=myRs.length;
//zuerst die Überschrift:
//erste Spalte enthält Dimension 1, die weiteren Spalten dann die Ausprägungen von Dimension 2:
var dimension1Value;
var dimension2Value;
var previousDimension1Value="";
var previousDimension2Value="";
var measure1Value;
var isFirstTargetRow=true;
myRs.forEach((row) => {
for (var col in row) {
//console.log(col +"-"+row[col]);
if(col==dimension1Fldname)
dimension1Value=row[col];
if(col==dimension2Fldname)
dimension2Value=row[col];
if(col==measure1Fldname)
measure1Value=row[col];
if(dimension1Value!=previousDimension1Value)
{
var datasetSourceRow=new Array();
var datasetSourceCol=new Array();
datasetSourceCol.push(dimension1Value);
if(dimension2Value!=previousDimension2Value)
datasetSourceCol.push(dimension2Value);
}
var datasetSourceCol=new Array();
datasetSourceCol.push(dimension1Value);
datasetSourceCol.push(measure1Value);
datasetSourceRow.push(datasetSourceCol);
}
});
//datasetSourceCol=[dimension1Fldname,dimension2Fldname,measure1Fldname];
//datasetSourceRow.push(datasetSourceCol);
//now the data:
//bei pie chartdimensions:myDimensionss ist die erste Spalte der Name, die zweite der Wert:
/*
for(var i=0;i < rowCount;i++)
{
var datasetSourceCol=new Array();
datasetSourceCol.push(myRs[i].dim_studiengang_fb);
datasetSourceCol.push(myRs[i].summe);
datasetSourceRow.push(datasetSourceCol);
}*/
return datasetSourceRow;
}
function fillEchartsDataSetNameValue(myRs,myRsMetaData,dimension1Fldname,measure1Fldname)
{
var datasetSourceRow=new Array();
var datasetSourceCol=new Array();
var columnCount=myRsMetaData.length;
var rowCount=myRs.length;
datasetSourceCol=[dimension1Fldname,measure1Fldname];
datasetSourceRow.push(datasetSourceCol);
//now the data:
//bei pie chartdimensions:myDimensionss ist die erste Spalte der Name, die zweite der Wert:
var dimension1Value;
var measure1Value;
myRs.forEach((row) => {
for (var col in row) {
//console.log(col +"-"+row[col]);
if(col==dimension1Fldname)
dimension1Value=row[col];
if(col==measure1Fldname)
measure1Value=row[col];
}
var datasetSourceCol=new Array();
datasetSourceCol.push(dimension1Value);
datasetSourceCol.push(measure1Value);
datasetSourceRow.push(datasetSourceCol);
});
/*
for(var i=0;i < rowCount;i++)
{
var datasetSourceCol=new Array();
datasetSourceCol.push(myRs[i].dim_studiengang_fb);
datasetSourceCol.push(myRs[i].summe);
datasetSourceRow.push(datasetSourceCol);
}*/
return datasetSourceRow;
}
/* plot and d3 start:*/
function renderPlotD3Chart(chartDiv,currentChartModel,ergebniselementOrdnr)
{
/*if(document.getElementById("chartName").value=="")
document.getElementById("chartName").value=vizInitialName;*/
if(currentChartModel.chartElements.length>0 && currentChartModel.chartElements[0])
{
renderChartSVGFromModel(currentChartModel,chartDiv,ergebniselementOrdnr);
}
else
document.getElementById(chartDiv).innerHTML="<svg style=\"width:100%;height: auto;\" viewBox=\"0 0 800 600\" width=\"800\" height=\"600\">"+
"<rect x=\"0\" y=\"0\" width=\"800\" height=\"450\" fill=\"#cccccc\"></rect></svg>";
//
}
/* Render Model:*/
function renderChartSVGFromModel(currentChartModel,targetDiv,ergebniselementOrdnr,title) {
//first update data if function is defined:
if(currentChartModel.dataTransformation.length>0)
{
for(var k=0;k< currentChartModel.dataTransformation.length;k++)
{
var myFunc=currentChartModel.dataTransformation[k];
for(var row=0;row < rs[ergebniselementOrdnr].length;row++)
{
rs[ergebniselementOrdnr][row][myFunc.colname]=applyFunction(rs[ergebniselementOrdnr][row][myFunc.colname],myFunc.colfunction);
}
}
}
switch (currentChartModel.renderer) {
case "plot":
renderChartSVGfromModelWithPlot(currentChartModel,targetDiv,ergebniselementOrdnr);
break;
case "d3js":
renderChartSVGWithD3(currentChartModel,targetDiv,ergebniselementOrdnr);
break;
case "echarts":
renderEChart2(currentChartModel,targetDiv,ergebniselementOrdnr,title);
break;
default:
alert("No renderer");
break;
}
return true;
}
function renderChartSVGfromModelWithPlot (currentChartModel,targetDiv,ergebniselementOrdnr)
{
console.log("using Plot");
var myOptions=new Object;
//myOptions.marks=new Array();
//myOptions.sort=new Array();
myOptions=getPlotOptionsObj(currentChartModel.chartPropertiesUsed,currentChartModel);
var marksArray=new Array();
/*for(var k=0;k< myChartModel.chartPropertiesUsed.length;k++)
{
}*/
//first empty marks:
for(var k=0;k< myOptions["marks"].length;k++)
{
myOptions["marks"][k].pop();
}
//copy ChartElements to marks:
for(var k=0;k< currentChartModel.chartElements.length;k++)
{
marksArray[k]=renderChartElementWithPlot(currentChartModel.chartElements[k],ergebniselementOrdnr);
/*Plot.barX(rs_table0,
{
x: "gesamt",
y: "eintrag",
fill: "blue"
}
*/
}
myOptions["marks"].push(marksArray);
var svgPlot=Plot.plot(myOptions);
var srcPlot=JSON.stringify(myOptions);
if(document.getElementById("chartCodeTextArea"))
document.getElementById("chartCodeTextArea").innerHTML=srcPlot;
document.getElementById(targetDiv).innerHTML="";
document.getElementById(targetDiv).appendChild(svgPlot);
//return svgPlot;
}
function renderChartSVGWithD3 (currentChartModel,targetDiv,ergebniselementOrdnr)
{
console.log("using D3JS");
var svgD3=new Object;
for(var k=0;k< currentChartModel.chartElements.length;k++)
{
svgD3=renderChartElementWithD3(currentChartModel,k,targetDiv,ergebniselementOrdnr);
}
//document.getElementById(targetDiv).innerHTML="";
//document.getElementById(targetDiv).appendChild(svgD3);
}
function renderChartElementWithD3(currentChartModel,chartElemNr,targetDiv,ergebniselementOrdnr)
{
// append the svg canvas to the page
var margin = { top: 10, right: 20, bottom: 10, left: 20 };
//var margin = { top: 0, right: 50, bottom: 0, left: 0 },
var width = Number(getChartPropertyFromModel(currentChartModel.chartPropertiesUsed,"width")) ;//margin.left - margin.right;
var height = Number(getChartPropertyFromModel(currentChartModel.chartPropertiesUsed,"height"));//margin.top - margin.bottom;
if(width <20)
width=630;
if(height <20)
height=430;
var clearCanvas=document.getElementById(targetDiv);
while (clearCanvas.firstChild) {
clearCanvas.removeChild(clearCanvas.firstChild);
}
//targetDiv
chartElem=currentChartModel.chartElements[chartElemNr];
if(chartElem)
{
var chartType=chartElem.vizTypeUniquename;
var rsIndexNr=ergebniselementOrdnr;
/*if(rs.length==1)
{
//if only 1 datasource is given, the indexNr is ignored
//this way a chartModel can be used in a macro *and* a single view
rsIndexNr=0;
}*/
var myDatasourceRs=rs[rsIndexNr];
var data=filld3data(rs[rsIndexNr],rsColumnMetaData[rsIndexNr],chartElem);
console.log("Mark-option for "+chartType);
switch (chartType)
{
case "sankey":
var mySvg = d3.select("#"+targetDiv).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", [0,0, width+ margin.left + margin.right, height+ margin.top + margin.bottom])
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
;
mySvg=makeSankeyD3(currentChartModel.chartPropertiesUsed,mySvg,data,rsColumnMetaData[chartElem.datasource],chartElem);
break;
case "worldmap":
var mySvg = d3.select("#"+targetDiv).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", [0,0, width+ margin.left + margin.right, height+ margin.top + margin.bottom])
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
;
mySvg=makeWorldmapD3(currentChartModel.chartPropertiesUsed,mySvg,data,rsColumnMetaData[chartElem.datasource],chartElem);
break;
case "pie":
var backgroundColorSelected=getChartPropertyFromModel(currentChartModel.chartPropertiesUsed,"backgroundColor",false);
var mySvg = d3.select("#"+targetDiv).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", [-(width+ margin.left + margin.right) / 2, -(height+ margin.top + margin.bottom) / 2, width+ margin.left + margin.right, height+ margin.top + margin.bottom])
.style("background-color", backgroundColorSelected)
.append("g")
;
mySvg=makePie_d3(currentChartModel.chartPropertiesUsed,mySvg,data,chartElem,width,height);
break;
case "sunburst":
width = 928;
height = width;
var mySvg = d3.select("#"+targetDiv).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", [-(width+ margin.left + margin.right) / 2, -(height+ margin.top + margin.bottom) / 2, width+ margin.left + margin.right, height+ margin.top + margin.bottom])
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
;
mySvg=makeSunburstD3(currentChartModel.chartPropertiesUsed,mySvg,rs[0],rsColumnMetaData[chartElem.datasource],chartElem);
break;
default:
alert("Unknown chart type");
break;
}
}
return mySvg;
}
function makeSunburstD3(myCommonChartProperties,svg,data,metaData,chartElem)
{
var sorted = d3.sort(data, d => d.dim_studiengang_fb_str,d => d.dim_studiengang_abschluss_grp_str, d => d.dim_studiengang_stg_str, d => d.summe);
var group = d3.group(sorted, d => d.dim_studiengang_fb_str,d => d.dim_studiengang_abschluss_grp_str, d => d.dim_studiengang_stg_str , d => d.summe );
//var sorted = d3.sort(data, d => d.dim_studiengang_fb_str,d => d.dim_studiengang_abschluss_grp_str, d => d.measure1);
//var group = d3.group(sorted, d => d.sos_stg_aggr_sem_rueck_beur_ein_str);
//console.log(group);
//var group = d3.group(sorted, d => d.dim_studiengang_fb_str,d => d.dim_studiengang_abschluss_grp_str, d => d.measure1 );
var hierarchy = d3.hierarchy(group);
var level1count=hierarchy.children.length;
console.log("level1count:"+level1count);
var data_str = "{\"name\":\"root\",\"children\":[";
for(var i=0; i < level1count ; i++){
console.log("Zeile "+i+ ":" + hierarchy.children[i].data[0]);
data_str+="{\"name\":\""+hierarchy.children[i].data[0]+"\",\"children\":[";
var level2count=hierarchy.children[i].children.length;
for(var j=0; j < level2count ; j++){
console.log("unterZeile "+j+ ":" + hierarchy.children[i].children[j].data[0]);
data_str+="{\"name\":\""+hierarchy.children[i].children[j].data[0]+"\",\"children\":[";
/*var level3count=hierarchy.children[i].children[j].children.length;
console.log("level3count: "+level3count);
for(var k=0; k < level3count ; k++){
console.log("unterUnterZeile "+k+ ":" + hierarchy.children[i].children[j].children[k].data[0]);
data_str+="{\"name\":\""+hierarchy.children[i].children[j].children[k].data[0]+"\",\"value\":"+hierarchy.children[i].children[j].children[k].children[0].data[0] +"}";
if(k < level3count -1)
data_str+=",";
}
*/
data_str+="]}";
if(j < level2count -1)
data_str+=",";
}
data_str+="]}";
if(i < level1count -1)
data_str+=",";
//console.log("Zeile "+i+ ":" + hierarchy.children[i].children[0].data);
}
data_str+="]}"
console.log(data_str);
var dataHierarchy=JSON.parse(data_str);
return renderSunburst(dataHierarchy,svg);
}
function renderSunburst(data,svg) {
// Specify the chart’s dimensions.
const width = 928;
const height = width;
const radius = width / 6;
// Create the color scale.
const color = d3.scaleOrdinal(d3.quantize(d3.interpolateRainbow, data.children.length + 1));
// Compute the layout.
const hierarchy = d3.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value);
const root = d3.partition()
.size([2 * Math.PI, hierarchy.height + 1])
(hierarchy);
root.each(d => d.current = d);
// Create the arc generator.
const arc = d3.arc()
.startAngle(d => d.x0)
.endAngle(d => d.x1)
.padAngle(d => Math.min((d.x1 - d.x0) / 2, 0.005))
.padRadius(radius * 1.5)
.innerRadius(d => d.y0 * radius)
.outerRadius(d => Math.max(d.y0 * radius, d.y1 * radius - 1))
// Create the SVG container.
// Append the arcs.
const path = svg.append("g")
.selectAll("path")
.data(root.descendants().slice(1))
.join("path")
.attr("fill", d => { while (d.depth > 1) d = d.parent; return color(d.data.name); })
.attr("fill-opacity", d => arcVisible(d.current) ? (d.children ? 0.6 : 0.4) : 0)
.attr("pointer-events", d => arcVisible(d.current) ? "auto" : "none")
.attr("d", d => arc(d.current));
// Make them clickable if they have children.
path.filter(d => d.children)
.style("cursor", "pointer")
.on("click", clicked);
const format = d3.format(",d");
path.append("title")
.text(d => `${d.ancestors().map(d => d.data.name).reverse().join("/")}\n${format(d.value)}`);
const label = svg.append("g")
.attr("pointer-events", "none")
.attr("text-anchor", "middle")
.style("user-select", "none")
.selectAll("text")
.data(root.descendants().slice(1))
.join("text")
.attr("dy", "0.35em")
.attr("fill-opacity", d => +labelVisible(d.current))
.attr("transform", d => labelTransform(d.current))
.text(d => d.data.name);
const parent = svg.append("circle")
.datum(root)
.attr("r", radius)
.attr("fill", "none")
.attr("pointer-events", "all")
.on("click", clicked);
// Handle zoom on click.
function clicked(event, p) {
parent.datum(p.parent || root);
root.each(d => d.target = {
x0: Math.max(0, Math.min(1, (d.x0 - p.x0) / (p.x1 - p.x0))) * 2 * Math.PI,
x1: Math.max(0, Math.min(1, (d.x1 - p.x0) / (p.x1 - p.x0))) * 2 * Math.PI,
y0: Math.max(0, d.y0 - p.depth),
y1: Math.max(0, d.y1 - p.depth)
});
const t = svg.transition().duration(750);
// Transition the data on all arcs, even the ones that aren’t visible,
// so that if this transition is interrupted, entering arcs will start
// the next transition from the desired position.
path.transition(t)
.tween("data", d => {
const i = d3.interpolate(d.current, d.target);
return t => d.current = i(t);
})
.filter(function(d) {
return +this.getAttribute("fill-opacity") || arcVisible(d.target);
})
.attr("fill-opacity", d => arcVisible(d.target) ? (d.children ? 0.6 : 0.4) : 0)
.attr("pointer-events", d => arcVisible(d.target) ? "auto" : "none")
.attrTween("d", d => () => arc(d.current));
label.filter(function(d) {
return +this.getAttribute("fill-opacity") || labelVisible(d.target);
}).transition(t)
.attr("fill-opacity", d => +labelVisible(d.target))
.attrTween("transform", d => () => labelTransform(d.current));
}
function arcVisible(d) {
return d.y1 <= 3 && d.y0 >= 1 && d.x1 > d.x0;
}
function labelVisible(d) {
return d.y1 <= 3 && d.y0 >= 1 && (d.y1 - d.y0) * (d.x1 - d.x0) > 0.03;
}
function labelTransform(d) {
const x = (d.x0 + d.x1) / 2 * 180 / Math.PI;
const y = (d.y0 + d.y1) / 2 * radius;
return `rotate(${x - 90}) translate(${y},0) rotate(${x < 180 ? 0 : 180})`;
}
return svg.node();
}
function makePie_d3(myCommonChartProperties,svg,data,chartElem,width,height)
{
//const width = 928;
//const height = Math.min(width, 500);
// Create the color scale.
const radius = Math.min(width, height) / 2;
var innerRadiusPercent = parseFloat(getChartPropertyFromModel(myCommonChartProperties,"innerRadius"),false);
var innnerRadiusComputed= radius * innerRadiusPercent / 100;
var myPalette=getChartPropertyFromModel(myCommonChartProperties,"scheme",false);
var textColor=getChartPropertyFromModel(myCommonChartProperties,"stroke",false);
var cornerRadius=getChartPropertyFromModel(myCommonChartProperties,"cornerRadius",false);
var labelRadiusFactor=parseFloat(getChartPropertyFromModel(myCommonChartProperties,"labelRadiusFactor",false))/100;
if(textColor=="")
textColor="black";
/*const color = d3.scaleOrdinal()
.domain(data.map(d => d.dimension1))
.range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), data.length).reverse())
const color = d3.scaleOrdinal()
.domain(data.map(d => d.dimension1))
.range(["#8cc277","#78a767","#1d71b8","#5b89c7","#2fac66"]); //Palette HMS
*/
//const color = d3.scaleOrdinal(d3.schemeAccent);
const color = d3.scaleOrdinal(getD3ColorScheme(myPalette));
/*const color = d3.scaleOrdinal()
.domain(data.map(d => d.dimension1))
.range(d3.schemePastel2)
;
*/
// Create the pie layout and arc generator.
const pie = d3.pie()
.sort(null)
.value(d => d.measure1);
const arc = d3.arc()
.innerRadius(innnerRadiusComputed )
.outerRadius(radius - 1)
.cornerRadius(cornerRadius);
const labelRadius = arc.outerRadius()() * labelRadiusFactor;
// A separate arc generator for labels.
const arcLabel = d3.arc()
.innerRadius(labelRadius)
.outerRadius(labelRadius+200);
const arcs = pie(data);
//svg.width=width;
//svg.height=width;
//d3.select(svg).attr("viewBox",[-width / 2, -height / 2, width, height]);
//svg.style="max-width: 100%; height: auto; font: 10px sans-serif;";
/*const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-width / 2, -height / 2, width, height])
.attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");
*/
// Add a sector path for each value.
svg.append("g")
.attr("stroke", "white")
.selectAll()
.data(arcs)
.join("path")
.attr("fill", d => color(d.data.dimension1))
.attr("d", arc)
.append("title")
.text(d => `${d.data.dimension1}: ${d.data.measure1.toLocaleString("de-DE")}`);
// Create a new arc generator to place a label close to the edge.
// The label shows the value if there is enough room.
svg.append("g")
.attr("text-anchor", "middle")
.selectAll()
.data(arcs)
.join("text")
.attr("transform", d => `translate(${arcLabel.centroid(d)})`)
.call(text => text.append("tspan")
.attr("y", "-0.4em")
//.attr("font-weight", "bold")
.attr("stroke", textColor)
.attr("fill", textColor)
.text(d => d.data.dimension1))
.call(text => text.filter(d => (d.endAngle - d.startAngle) > 0.25).append("tspan")
.attr("x", 0)
.attr("y", "0.7em")
.attr("fill-opacity", 0.7)
.text(d => d.data.measure1.toLocaleString("de-DE")));
//return svg.node();
return svg.node();
}
function makeWorldmapD3(myCommonChartProperties,mySvg,data,metaData,chartElem)
{
// load the data
var captionEmptyTarget=getChartPropertyFromModel(myCommonChartProperties,"null_value_mask");
renderWorldMap(myCommonChartProperties,mySvg,data);
}
function renderWorldMap(myCommonChartProperties,mySvg,data)
{
const worldWidth = 670;
const worldHeight = 450;
const worldTooltip = d3.select(".vizTooltip");
const worldColor = d3.scaleSequential(d3.interpolateBlues)
.domain([0, 1]); // Domain matches the output of logColor
const worldLogColor = d3.scaleLog()
.domain([1, 41227]) // Adjust this domain to fit your data range
.range([0, 1]);
const worldSvg = d3.select("#world-map")
.attr("width", worldWidth)
.attr("height", worldHeight);
const worldProjection = d3.geoMercator()
.scale(100)
.translate([worldWidth / 2, worldHeight / 1.5]);
const worldPath = d3.geoPath().projection(worldProjection);
var d=getWorldMapData(data);
// Load the world data files
Promise.all([
/*d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson"),*/
/*d3.csv("/superx/viz_worldmap/data.csv", d => ({
iso3: d.iso3,
value: +d.value
}))*/
d3.json("../xml/js/viz/world.geojson"),
/*getLocalJson("/superx/xml/js/viz/world_superx2.geojson"),*/
d
]).then(([worldGeojson, worldData]) => {
const worldDataMap = new Map(worldData.map(d => [d.iso3, d.value]));
mySvg.append("g")
.selectAll("path")
.data(worldGeojson.features)
.enter().append("path")
.attr("d", worldPath)
.attr("fill", d => {
const value = worldDataMap.get(d.id); // Use `d.id` to access ISO 3 codes
if (value === 0) return "#ccc"; // Handle zero values separately
return value ? worldColor(worldLogColor(value)) : "#ccc";
})
.on("mouseover", function (event, d) {
const value = worldDataMap.get(d.id);
worldTooltip.transition()
.duration(200)
.style("opacity", .9);
worldTooltip.html(d.properties.name + "<br>" + (value ? value : "No data"))
.style("left", (event.pageX) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function () {
worldTooltip.transition()
.duration(500)
.style("opacity", 0);
});
}).catch(error => {
console.error('Error loading or parsing data:', error);
});
async function getLocalJson(url)
{
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Serverantwort: ${response.status}`);
}
const myJson = await response.json();
return myJson;
} catch (error) {
console.log(error.message);
}
}
function getWorldMapData(data)
{
var myData=[];
var zs="";
for (var i = 0; i < data.length; i++)
{
myData[i] = { "iso3": data[i].dimension1, "value": data[i].measure1 };
}
return myData;
}
}
function makeSankeyD3(myCommonChartProperties,mySvg,data,metaData,chartElem)
{
// load the data
var captionEmptyTarget=getChartPropertyFromModel(myCommonChartProperties,"null_value_mask");
if(captionEmptyTarget=="")
captionEmptyTarget="Leer";
var sNodes=getSankeyNodes(data,captionEmptyTarget); //graph.nodes;
var sLinks=getSankeyLinks(sNodes,data); //graph.links;
renderSankey(myCommonChartProperties,mySvg,sNodes,sLinks);
//var myChartSVG = SankeyChart(sNodes,sLinks);
}
function getSankeyNodes(data,captionEmptyTarget)
{
var myNodes=[];
var distinctSource = [];
var zs="";
for (var i = 0; i < data.length; i++)
{
if(zs.indexOf("_" + data[i].dimension1 +"_")<0)
{
distinctSource.push(data[i].dimension1);
zs+="_" + data[i].dimension1 +"_";
}
}
for (var i = 0; i < data.length; i++)
{
if(zs.indexOf("_" + data[i].dimension2 +"_")<0)
{
distinctSource.push(data[i].dimension2);
zs+="_" + data[i].dimension2 +"_";
}
}
for (var i = 0; i < distinctSource.length; i++)
{
myNodes[i] = { "node": i, "name": distinctSource[i] };
console.log("Abschluss: "+distinctSource[i]);
}
//Kein Abschluss:
myNodes[i] = { "node": i, "name": captionEmptyTarget };
return myNodes;
}
function getSankeyLinks(myNodes,data)
{
var myLinks=[];
var linkIndex=0;
for (var i = 0; i < data.length; i++)
{
if(data[i].dimension2 !="")
{
myLinks[linkIndex]={ "source": getSankeyNodeIndex(myNodes,data[i].dimension1),
"target": getSankeyNodeIndex(myNodes,data[i].dimension2), "value":data[i].measure1 };
linkIndex++;
}
else
{
myLinks[linkIndex]={ "source": getSankeyNodeIndex(myNodes,data[i].dimension1),
"target": myNodes.length-1, "value":data[i].measure1 };
linkIndex++;
}
}
return myLinks;
}
function getSankeyNodeIndex(myNodes,name)
{
var myIndex=0;
for (var i = 0; i < myNodes.length; i++)
{
if(myNodes[i].name==name)
myIndex=i
}
return myIndex;
}
function getMeasureCaption(chartElem,metaData)
{
var measureCaption="";
for(var k=0;k<chartElem.elementTypeProperties.length;k++)
{
if(chartElem.elementTypeProperties[k].propertyValue!="")
{
switch (chartElem.elementTypeProperties[k].vizTypePropertyUniquename)
{
case "viz_measure1":
measure1=chartElem.elementTypeProperties[k].propertyValue;
measureCaption=getMetadataOfVizTypeProperty(metaData,measure1);
if(measureCaption=="")
measureCaption=measure1;
break;
default:
break;
}
}
}
return measureCaption;
}
function getMetadataOfVizTypeProperty(metaData,vizTypePropertyUniquename)
{
var caption="";
for(var k=0;k<metaData.length;k++)
{
if(metaData[k].colname==vizTypePropertyUniquename)
{
caption=metaData[k].colcaption;
}
}
return caption;
}
function renderSankey(myCommonChartProperties,svg,sNodes,sLinks)
{
// set the dimensions and margins of the graph
var margin = { top: 10, right: 10, bottom: 10, left: 10 },
//var margin = { top: 0, right: 50, bottom: 0, left: 0 },
width = getChartPropertyFromModel(myCommonChartProperties,"width") - margin.left - margin.right,
height = getChartPropertyFromModel(myCommonChartProperties,"height") - margin.top - margin.bottom;
if(width <20)
width=630;
if(height <20)
height=430;
// format variables
var formatNumber = d3.format(",.0f"), // zero decimal places
format = function (d) { return formatNumber(d); },
color = d3.scaleOrdinal().range(["#002060ff", "#164490ff", "#4d75bcff", "#98b3e6ff", "#d5e2feff", "#008cb0ff"]);
var textColor=getChartPropertyFromModel(myCommonChartProperties,"color");
if(textColor=="")
textColor="#3f3f3f";
var fontSize=getChartPropertyFromModel(myCommonChartProperties,"fontSize");
if(fontSize=="")
fontSize="12pt";
var fontFamily=getChartPropertyFromModel(myCommonChartProperties,"fontFamily");
if(fontFamily=="")
fontFamily="sans-serif";
// append the svg object to the body of the page
/*const sankeyDiv = svg.selectAll("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
*/
// Set the sankey diagram properties
var sankey = d3.sankey()
.nodeWidth(100)
.nodePadding(40)
.size([width, height]);
var path = sankey.links();
var data=new Object;
data.nodes=sNodes;
data.links=sLinks;
var graph=sankey(data);
// add in the links
var link = svg.append("g").selectAll(".link")
.data(graph.links)
.enter().append("path")
.attr("class", "link")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke-width", function (d) { return d.width; });
// add the link titles
link.append("title")
.text(function (d) {
return d.source.name + " → " +
d.target.name+": "+d.value;
});
// add in the nodes
var node = svg.append("g").selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
// add the rectangles for the nodes
node.append("rect")
.attr("x", function (d) { return d.x0; })
.attr("y", function (d) { return d.y0; })
.attr("height", function (d) { return d.y1 - d.y0; })
.attr("width", sankey.nodeWidth())
.style("fill", function (d) {
var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
var col = "rgb(" + r + "," + g + "," + b + ")";
return d.color = col;
})
/*.style("fill", d3.schemaPastel2)*/
// Attempt at getting whole length of link to highlight
.on("mouseover", function (d) {
link
.transition()
.duration(300)
.style("stroke-opacity", function (l) {
return l.source === d || l.target === d ? 0.5 : 0.2;
});
})
.on("mouseleave", function (d) {
link
.transition()
.duration(300)
.style("stroke-opacity", 0.2);
})
// Node hover titles
.append("title")
.text(function (d) {
return d.name + "\n" + format(d.value);
});
// add in the title for the nodes
node.append("text")
.style("fill", textColor)
.attr("x", function (d) { return d.x0 - 6; })
.attr("y", function (d) { return (d.y1 + d.y0) / 2; })
.attr("dy", "0.35em")
.attr("font-size",fontSize)
.attr("font-family",fontFamily)
.attr("text-anchor", "end")
.text(function (d) { return d.name; })
.filter(function (d) { return d.x0 < width / 2; })
.attr("x", function (d) { return d.x1 + 6; })
.attr("text-anchor", "start")
;
// add in the title for the nodes
/*node.append("text")
.style("fill", textColor)
.attr("x", function (d) { return d.x0 - 6; })
.attr("y", function (d) { return (d.y1 + d.y0) / 2; })
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(function (d) { return d.name; })
.filter(function (d) { return d.x0 < width / 2; })
.attr("x", function (d) { return d.x1 + 6; })
.attr("text-anchor", "start")
;*/
// add in the value labels for the nodes
node.append("text")
.style("fill", textColor)
.attr("x", function (d) { return d.x0+20; }) //rechte Seite
.attr("y", function (d) { return (d.y1 + d.y0) / 2; })
.attr("dy", "0.35em")
.attr("font-size",fontSize)
.attr("font-family",fontFamily)
.attr("text-anchor", "start")
.text(function (d) { return d.value; })
.filter(function (d) { return d.x0 < width / 2; })
.attr("x", function (d) { return d.x1 -40; }) //linke Seite
.attr("text-anchor", "start")
;
}
function renderChartElementWithPlot(chartElem,ergebniselementOrdnr)
{
var plotMark=new Object;
if(chartElem)
{
var chartType=chartElem.vizTypeUniquename;
var rsIndexNr=ergebniselementOrdnr;
/*if(rs.length==1)
{
//if only 1 datasource is given, the indexNr is ignored
//this way a chartModel can be used in a macro *and* a single view
rsIndexNr=0;
}*/
var myDatasourceRs=rs[rsIndexNr];
var optionString=prepareChartPropertiesForPlotMark(chartType,chartElem);
console.log("Mark-option for "+chartType+":"+ optionString);
var markOptions=JSON.parse(optionString);
switch (chartType)
{
case "bar_x":
plotMark=Plot.barX(myDatasourceRs,markOptions);
break;
/* case "bar_x_stacked":
plotMark=Plot.barX(myDatasourceRs,markOptions);
break;*/
case "bar_x_alt":
makeBarX(svg,data);
break;
case "bar_y":
plotMark=Plot.barY(myDatasourceRs,markOptions);
break;
case "area_x":
plotMark=Plot.areaX(myDatasourceRs,markOptions);
break;
case "area_y":
plotMark=Plot.areaY(myDatasourceRs,markOptions);
break;
case "dot":
plotMark=Plot.dot(myDatasourceRs,markOptions);
break;
case "line":
plotMark=Plot.line(myDatasourceRs,markOptions);
break;
case "box_x":
plotMark=Plot.boxX(myDatasourceRs,markOptions);
break;
case "box_y":
plotMark=Plot.boxY(myDatasourceRs,markOptions);
break;
case "text":
plotMark=Plot.text(myDatasourceRs,markOptions);
break;
default:
alert("Unknown chart type");
break;
}
}
return plotMark;
}
function prepareChartPropertiesForPlotMark(chartType,chartElem)
{
var orientation=getVizTypeOrientation(chartElem.vizTypeUniquename);
var optionString="{\"dummy\": \"1\"";
for(var k=0;k<chartElem.elementTypeProperties.length;k++)
{
var propUniquename=chartElem.elementTypeProperties[k].vizTypePropertyUniquename;
var propValue=chartElem.elementTypeProperties[k].propertyValue;
var propertyType=getVizTypePropertyType(propUniquename);
var textDelim="";
if(propValue!="")
{
textDelim="\"";
//wg. Abwärtskompatibilität ist der Default delim STRING
if(propertyType
&& propertyType !="string")
textDelim="";
optionString+=",\""+propUniquename+"\":"+textDelim+propValue+textDelim;
if(propUniquename=="stroke" && chartType!="line")
{
//Seriendimension hat immer fill
optionString+=",\"fill\":\""+propValue+"\"";
//optionString+=",\"sort\":\""+propValue+"\"";
}
if(propUniquename=="text")
{
//Wertelabel
optionString+=",\"textAnchor\":\"start\"";
}
if(propUniquename=="sortchannel" && propValue !="" && orientation=="V")
{
//Zusätzliche Sortierung vertikale Diagramme:
optionString+=",\"channels\": {\"sort1\": {\"value\": \""+propValue+"\"}},\"sort\": {\"x\": \"sort1\"}";
}
if(propUniquename=="sortchannel" && propValue !="" && orientation=="H")
{
//Zusätzliche Sortierung horizontale Diagramme:
optionString+=",\"channels\": {\"sort1\": {\"value\": \""+propValue+"\"}},\"sort\": {\"y\": \"sort1\"}";
}
if(propUniquename=="fill_static" )
{
if(optionString.indexOf("\"fill\"") ==-1) //nur wenn es nicht als channel genutzt wird
optionString+=",\"fill\":\""+propValue+"\"";
}
if(propUniquename=="stroke_static" )
{
if(optionString.indexOf("\"stroke\"") ==-1) //nur wenn es nicht als channel genutzt wird
optionString+=",\"stroke\":\""+propValue+"\"";
}
}
}
optionString+=" }";
return optionString;
}
function getVizTypeOrientation(vizTypeUniquename)
{
var orientation="";
for(var k=0;k<vizTypes.length;k++)
{
if(vizTypes[k].uniquename==vizTypeUniquename)
orientation=vizTypes[k].orientation;
}
return orientation;
}
function getVizTypePropertyType(propUniquename)
{
var propertyType="";
for(var k=0;k<commonChartProperties.length;k++)
{
if(commonChartProperties[k].name==propUniquename)
propertyType=commonChartProperties[k].propValueType;
}
return propertyType;
}
function getPlotOptionsObj(chartPropertiesUsed,currentChartModel)
{
var commonChartPropertyGroups=[];
var previousGroup="";
var optionsString="{";//"\"width\":100,\"height\":100,";
optionsString+="\"caption\":\""+getChartPropertyValue(chartPropertiesUsed,"caption")+"\"";
for(var k=0;k < commonChartProperties.length;k++)
{
var groupVariableName=commonChartProperties[k].groupVariableName;
if(groupVariableName!=""
&& groupVariableName != previousGroup)
{
var newcommonChartPropertyGroup = new commonChartPropertyGroup(commonChartProperties[k].groupCaption,commonChartProperties[k].groupUniquename,groupVariableName);
commonChartPropertyGroups.push(newcommonChartPropertyGroup);
}
previousGroup=groupVariableName;
}
//Now create options Str with all groups:
var textDelim="";
for(var i=0;i < commonChartPropertyGroups.length;i++)
{
if(commonChartPropertyGroups[i].groupVariableName!="layout")
optionsString+=",\""+commonChartPropertyGroups[i].groupVariableName+"\":{\"dummy1\":1";
for(var k=0;k < commonChartProperties.length;k++)
{
if(commonChartProperties[k].groupVariableName==commonChartPropertyGroups[i].groupVariableName
&& commonChartProperties[k].variableName!=""
&& getChartPropertyValue(chartPropertiesUsed,commonChartProperties[k].name)!=""
&& !isChartPropertyValidForChartelements(commonChartProperties[k],currentChartModel))
{
textDelim=(commonChartProperties[k].propValueType=="string" || commonChartProperties[k].propUnit!="")?"\"":"";
optionsString+=",\""+commonChartProperties[k].variableName+"\":"+textDelim+getChartPropertyValue(chartPropertiesUsed,commonChartProperties[k].name)+textDelim;
}
}
if(commonChartPropertyGroups[i].groupVariableName!="layout")
optionsString+=" }"; //close tag
}
optionsString+= ", \"marks\":[]";
optionsString+=" }"; //close tag
console.log("General Options: "+optionsString);
var chartOptions=JSON.parse(optionsString);
return chartOptions;
}
/*echarts:*/
function renderEChart2(currentChartModel,chartDiv,ergebniselementOrdnr,chartTitle)
{
//first empty the element, if necessary:
var chartDivElem=document.getElementById(chartDiv);
while (chartDivElem.firstChild) {
chartDivElem.removeChild(chartDivElem.firstChild);
}
// Initialize the echarts instance based on the prepared dom
if(echarts && chartDivElem!=null)
echarts.dispose(chartDivElem);
//echarts.registerLocale('DE', lang);
var myChart = echarts.init(chartDivElem,null, { renderer: 'svg', locale: 'DE'});
var chartType=currentChartModel.chartElements[0].vizTypeUniquename;
var titleText=chartTitle;
if(chartTitle=="")
titleText=getChartPropertyValue(currentChartModel.chartPropertiesUsed,"caption");
var myDataset=fillEchartsDataSet(rs[ergebniselementOrdnr],rsColumnMetaData[ergebniselementOrdnr],currentChartModel);
var option;
switch (chartType)
{
case "echarts_bar_x":
case "echarts_bar_y":
case "echarts_line_x":
case "echarts_line_y":
option=getEchartOptionsBarLine(currentChartModel,myDataset,chartType,titleText);
break;
case "echarts_pie":
option=getEchartOptionsPie(currentChartModel,myDataset,titleText);
break;
case "echarts_native":
option=getEchartOptionsNative(currentChartModel,myDataset,titleText);
break;
default:
alert("Unknown chart type");
break;
}
// Display the chart using the configuration items and data just specified.
console.log("ECharts-SRC:"+JSON.stringify(option));
//im Assistenten den Code setzen:
if(document.getElementById("chartCodeTextArea"))
document.getElementById("chartCodeTextArea").innerHTML=prettifyJson(JSON.stringify(option));
myChart.setOption(option);
}
/*
function determineChartSkeleton(datasourceDef,ergebniselementOrdnr)
{
var dsChartElement=datasourceDef.chartElements[ergebniselementOrdnr];
var dimension1Prop = dsChartElement.elementTypeProperties.find(o => o.vizTypePropertyUniquename == "dimension1");
var dimension1Caption=dimension1Prop.caption;
var dimension1Fldname=dimension1Prop.propertyValue;
var dimension2Prop = "";
var dimension2Caption="";
var dimension2Fldname="";
var dimension2Prop=dsChartElement.elementTypeProperties.find(o => o.vizTypePropertyUniquename == "dimension2");
if(dimension2Prop)
{
dimension2Caption=dimension2Prop.caption;
dimension2Fldname=dimension2Prop.propertyValue;
}
var measure1Prop = dsChartElement.elementTypeProperties.find(o => o.vizTypePropertyUniquename == "measure1");
var measure1Caption=measure1Prop.caption;
var measure1Fldname=measure1Prop.propertyValue;
var skel= new chartSkeleton(ergebniselementOrdnr,
title,
subtitle,
dimension1Fldname,
dimension1Caption,
dimension2Fldname,
dimension2Caption,
measure1Fldname,
measure1Caption,
measure2Fldname,
measure2Caption
);
chartSkeleton(nr,
title,
subtitle,
dimension1Fldname,
dimension1Caption,
hasDimension2,
dimension2Fldname,
dimension2Caption,
measure1Fldname,
measure1Caption,
hasMeasure2,
measure2Fldname,
measure2Caption
} */
function closeModalCardDetail(ergebniselementOrdnr)
{
var myModalCard=document.getElementById("modalCardDetail"+ergebniselementOrdnr);
myModalCard.classList.remove('is-active');
}
function getEchartOptionsBarLine(currentChartModel,myDataset,chartType,titleText)
{
//TODO: bar_x und y abfangen'
var chartTypes = chartType.split(/_/);
var orientation=chartTypes[2];
var measure1Axis="y";
var dimension1Axis="x";
var xAxisType="category";
var yAxisType="value";
if(orientation=="x")
{
measure1Axis="x";
dimension1Axis="y";
yAxisType="category";
xAxisType="value";
}
//var measure1Fldname=getChartPropertyValue(currentChartModel.chartPropertiesUsed,measure1Axis);
var measure1Fldname=getChartElementPropertyValueFromModel(currentChartModel,1,measure1Axis);
var dimension1Fldname=getChartElementPropertyValueFromModel(currentChartModel,1,dimension1Axis);
//var dimension1Fldname=getChartPropertyValue(currentChartModel.chartPropertiesUsed,dimension1Axis);
var subtitleText=getChartPropertyValue(currentChartModel.chartPropertiesUsed,"subtitle");
var scheme = getChartPropertyValue(currentChartModel.chartPropertiesUsed,"scheme");
var myPalette=getSchemeArray(scheme);
var encodeObj={x:dimension1Fldname,y:measure1Fldname};
if(orientation=="x")
encodeObj={y:dimension1Fldname,x:measure1Fldname};
var option = {
dataset: myDataset,
/*klappt nicht, noch testen: transfxAxis: {
typeorm: {
type: 'sort',
config: { dimension: "dim_studiengang_fb", order: 'asc' }
}
,*/
title: {
text: titleText,
subtext: subtitleText,
left: "center",
top: "top",
textStyle: {
fontSize: 20
},
subtextStyle: {
fontSize: 15
}
},
grid: {
top: "16%",
left: "20%"
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow"
},/*
formatter: function (value, index) {
return numberFormatter(value,"value");
}*/
valueFormatter: (value) => numberFormatter(value,"value")
},
xAxis: {
type:xAxisType, //horizontal oder vertikal
//type: 'category',
axisLabel: {
inside: false,
margin: 15,
fontSize: 12,
width:"100px",
rotate: 30,
formatter: function (value, index) {
return numberFormatter(value,xAxisType);
}
}
},
yAxis: {
//type:'value',
type: yAxisType,
axisLabel: {
inside: false,
margin: 5,
fontSize: 12,
width:"50px",
formatter: function (value, index) {
return numberFormatter(value,yAxisType);
}
}
},
series: [
{
type: chartTypes[1], //bar,line
encode: encodeObj,
barWidth: '30%',
showBackground: true,
backgroundStyle: {
color: '#dfe4f2'
},
margin: 50,
fontSize: 14,
colorBy: 'data',
lineStyle: {
width: 7
},
label: {
show: true
},
labelLayout(params) {
return getLabelLayout(params,orientation)
}
}
],
color:myPalette
};
return option;
}
/* Labels bei Balkendiagramm je nach Orientierung
- horizontal: rechts neben Balken
- vertikal: zentriert im Balken
*/
function getLabelLayout(params,orientation)
{
if(orientation=="x")
{
return {
x: params.rect.x +params.rect.width+ 30,
y: params.rect.y + params.rect.height / 2,
verticalAlign: 'middle',
align: 'right'
};
}
else
return {verticalAlign: 'middle'};
}
function getEchartOptionsNative(currentChartModel,myDataset)
{
var options=currentChartModel.chartElements[0].sourceCode;
options.dataset=myDataset;
//var dataset ={dataset};
//dataset.source=myDataset;
//options=Object.assign(myDataset,options);
return options;
}
function getEchartOptionsPie(currentChartModel,myDataset)
{
var measure1Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","measure1");
var dimension1Fldname=getChartElementPropertyValueFromModel(currentChartModel,"1","dimension1");
var titleText=getChartPropertyValue(currentChartModel.chartPropertiesUsed,"caption");
var scheme = getChartPropertyValue(currentChartModel.chartPropertiesUsed,"scheme");
var myPalette=getSchemeArray(scheme);
var option = {
dataset: {
source: myDataset
},
title: {
text: titleText,
subtext: "",
left: "left",
top: "top",
textStyle: {
fontSize: 20
},
subtextStyle: {
fontSize: 15
}
},
series: [
{
type: 'pie',// sunburst
/*encode: {
value: measure1Fldname,
name: dimension1Fldname
},*/
tooltip: {
trigger: "item"
},
stillShowZeroSum: false,
label: {
show: true,
formatter: '{c}',
width:200
},
fontSize: 12,
radius: ['30%', '80%'], //1. Parameter inside radius, macht ihn zum Donut. 2.Parameter definiert den Anteil des Kreises am ganzen Viewport"
color: myPalette,
itemStyle: {
//borderRadius: [20, 5, 5, 10], //abgerundete Ecken der Tortenstücke
borderColor: '#fff',
borderWidth: 2
}
}
]
};
return option;
}
function getChartPropertyValue(propArray,propName)
{
var propertyValue="";
if(propArray)
{
for (var i=0;i<propArray.length;i++)
{
if(propArray[i].name==propName )
{
propertyValue=propArray[i].propertyValue;
if(propArray[i].propUnit && propArray[i].propUnit !="")
propertyValue+=propArray[i].propUnit;
}
}
}
return propertyValue;
}
function getChartElementPropertyValueFromModel(myChartModel,elemID,propUniquename)
{
var elemID="1";
var retVal=null;
var myChartElem=null;
if(myChartModel.chartElements && elemID !=null)
{
var filtered=myChartModel.chartElements.filter(obj => obj.elemID == elemID);
var myChartElem=filtered[0];
if(myChartElem.elementTypeProperties && myChartElem.elementTypeProperties.length)
{
for(var k=0;k < myChartElem.elementTypeProperties.length;k++)
{
myVizTypeProperty=myChartElem.elementTypeProperties[k];
if(myVizTypeProperty.vizTypePropertyUniquename==propUniquename)
{
retVal=myVizTypeProperty.propertyValue;
}
}
}
}
return retVal;
}
function getChartPropertyFromModel(myChartProperties,name,isCommon)
{
var propertyValue="";
if(myChartProperties && myChartProperties.length>0)
{
let prop = myChartProperties.find(o => o.name === name);
if(!prop)
prop = myChartProperties.find(o => o.vizTypePropertyUniquename == name);
if(prop)
propertyValue=prop.propertyValue;
}
//if no value is set from model, retrieve the default value:
if(propertyValue=="" && isCommon)
propertyValue=getCommonChartProperty(name);
return propertyValue;
}
function getCommonChartProperty(name)
{
var propertyValue="";
if(document.forms["chartPropertiesForm"] && document.forms["chartPropertiesForm"].elements[name])
{
propertyValue=document.forms["chartPropertiesForm"].elements[name].value;
}
if(propertyValue=="")
{
let prop = commonChartProperties.find(o => o.name === name);
if(prop.defaultValue!="")
{
propertyValue=prop.defaultValue;
}
}
/*for (var i=0;i<commonChartProperties.length;i++)
{
if(commonChartProperties[i].name==name && document.forms["chartPropertiesForm"].elements[name])
{
propertyValue=document.forms["chartPropertiesForm"].elements[name].value;
if(propertyValue=="" && commonChartProperties[i].defaultValue!="")
{
propertyValue=commonChartProperties[i].defaultValue;
}
}
}*/
return propertyValue;
}
function filld3data(myRs,MyRsMetaData,chartElem)
{
//Identify dimensions and measures:
var dimension1,dimension2,measure1;
var data=[];
for(var k=0;k<chartElem.elementTypeProperties.length;k++)
{
if(chartElem.elementTypeProperties[k].propertyValue!="")
{
switch (chartElem.elementTypeProperties[k].vizTypePropertyUniquename)
{
case "dimension1":
dimension1=chartElem.elementTypeProperties[k].propertyValue;
case "dimension2":
dimension2=chartElem.elementTypeProperties[k].propertyValue;
break;
case "measure1":
measure1=chartElem.elementTypeProperties[k].propertyValue;
break;
default:
break;
}
}
}
//get MetaData:
//alert(dimension1+"-"+dimension2+"-"+measure+"-"+ functionOfCategoryDim+"-"+functionOfDimension2+"-"+functionOfMeasureDim);
//get and transform Data:
var maxLenDimension1=0;
var maxMeasure=0;
var rowcount=myRs.length;
var rownr=1;
console.log("Zeilenanzahl " +rowcount);
myRs.forEach((row) => {
for (var col in row) {
console.log(col +"-"+row[col]);
if(col==dimension1)
dimension1Value=row[col];
if(col==dimension2)
dimension2Value=row[col];
if(col==measure1)
measure1Value=row[col];
}
data.push(new d3dataRow(rownr,dimension1Value,dimension2Value,measure1Value));
rownr++;
}
);
/*
console.log(rownr +"-" + dimension1Value +"-" +dimension2Value +"-" +measureDimValue);
selectionRs.push(new d3dataRow(rownr,dimension1Value,dimension2Value,measureDimValue));
//identify max String length to compute x axis size
if(dimension1Value.length >maxLenDimension1)
maxLenDimension1=dimension1Value.length;
//the same for values:
if(measureDimValue >maxMeasure)
maxMeasure=measureDimValue;
}
//TODO:Sorting and filtering
*/
return data;
}
function isChartPropertyValidForChartelements(prop,currentChartModel)
{
var propValid=false;
if(prop.isGeneric==1)
return true;
var nrOfChartElements=currentChartModel.chartElements.length;
for(var k=0;k < nrOfChartElements;k++)
{
var usedVizTypeUniquename=currentChartModel.chartElements[k].vizTypeUniquename;
for(var i=0;i < vizTypeProperties.length;i++)
{
if(vizTypeProperties[i].propUniquename==prop.name
&& vizTypeProperties[i].typeUniquename==usedVizTypeUniquename)
propValid=true;
}
}
return propValid;
}
function getD3ColorScheme(name,size)
{
//blues|greens|greys|oranges|purples|reds|paired|set1|pastel1|pastel2|tableau10|category10|accent|dark2
if(size==null || size==0)
size=9;
switch (name) {
case "blues":
return d3.schemeBlues[size];
break;
case "greens":
return d3.schemeGreens[size];
break;
case "greys":
return d3.schemeGreys[size];
break;
case "oranges":
return d3.schemeOranges[size];
break;
case "purples":
return d3.schemePurples[size];
break;
case "reds":
return d3.schemeReds[size];
break;
case "accent":
return d3.schemeAccent;
break;
case "paired":
return d3.schemePaired;
break;
case "set1":
return d3.schemeSet1;
break;
case "category10":
return d3.schemeCategory10;
break;
case "dark2":
return d3.schemeDark2;
break;
case "pastel1":
return d3.schemePastel1;
break;
case "pastel2":
return d3.schemePastel2;
break;
case "tableau10":
return d3.schemeTableau10;
break;
case "custom1":
return ["#5b89c7","#2fac66","#8cc277","#78a767","#1d71b8"];
break;
default:
return d3.schemePastel2;
break;
}
}
function vizTabelleComboOderSichtLaden(maskentid,fname, caption,fnameEscaped,zeilenanzahl,feldart,referrerForm) {
Feldname = fname;
var callurl = '/superx/servlet/SuperXmlMaske';
callurl += "?tid=" + maskentid + "&getJSON_" + getEncoded(Feldname) +
'=xxxxxx-xxxxxx@';
var params = "";
var myElements= new Array();
myElements=document.forms["Weiterverarbeitung"].elements;
var e=document.forms["Weiterverarbeitung"].elements[fname];
for (var i = 1; i < felder.length; i++)
{
e = myElements[felder[i]["htmlname"]];
if (e) {
var t = e.type;
var name = felder[i]["name"];
if (t == 'text')
{
//todo bei startsWith select_ label_ auch überspringen
if (e.value != '') //leere Felder müssen auch übergeben werden MB!!
// 1/2016 MB dies geht nicht weil ISO kodiert
//params+="&"+felder[i]["cb_name"]+"="+encodeURIComponent(e.value);
params += "&" + getEncoded(felder[i]["htmlname"]) + "=" + getEncoded(e.value);
else
params += "&" + getEncoded(felder[i]["htmlname"]) + "=--leer--";
}
}
}
console.log("PARAMS:"+params);
//return false;
var currentFieldValue=document.forms['Weiterverarbeitung'].elements[Feldname].value;
/*var splitchar=",";
if(currentFieldValue.indexOf("|")>-1)
splitchar="\|";
var currentFieldValueArray = currentFieldValue.split(splitchar);
var currentFieldValueCount=currentFieldValueArray.length;
*/
params=encodeURIComponent(params);
//alert(params);
var jspPage="maske_combo_laden.jsp";
if(feldart==12)
jspPage="maske_sicht_laden.jsp";
var editurl="/superx/edit/kern/"+jspPage+"?tid="+maskentid+ "&Feldname="+getEncoded(fname)+"&previousValue="+currentFieldValue;
editurl +="&zeilenanzahl="+zeilenanzahl+"&referrerForm=Weiterverarbeitung&params="+params;
neu2=window.open(editurl,"_blank","directories=no,location=no,menubar=no,scrollbars=yes,resizable=yes,toolbar=no,width=800,height=660");
}
function applyFunction(theValue,theFunction)
{
switch (theFunction) {
case "switchWord1and2ff":
var ret=switchWord1and2ff(theValue);
break;
case "justWord1":
var ret=justWord1(theValue);
break;
case "abbreviate":
var ret=abbreviate(theValue,20);
break;
default:
var ret=theValue;
break;
}
return ret;
}
function switchWord1and2ff(theString)
{
//erzeugt z.B. aus "WiSe 2020/2021" den Wert "2020/2021", zum Sortieren
var theWords = theString.split(/ /);
var word1=theWords[0];
var word2="";
var ret="";
if(theWords.length >1)
{
for(var k=1;k < theWords.length;k++)
{
word2+= theWords[k];
}
ret +=word2;
}
ret+=" "+ word1;
return ret.trim();
}
function justWord1(theString)
{
//nur erstes Wort, zum Sortieren
var word1End=-1;
var i=0;
var endFound=false;
do{
var myChar=theString.substr(i,1);
if(myChar=="|" || myChar==" "|| myChar=="-")
{
endFound=true;
word1End=i;
}
else
i++;
}
while (endFound==false && i<=theString.length);
if(word1End==-1)
word1End=theString.length;
return theString.substr(0,word1End);
}
function abbreviate(theString,theMaxLength)
{
//nur erste x Zeichen
if(theString.length > theMaxLength)
{
var theCut = theString.substr(0,theMaxLength-3)+"...";
return theCut;
}
else return theString.trim();
}
function getColumnCaption(columnName)
{
let rsMetaDataLen = rsMetaData.length;
var colCaption=columnName;
for (let i = 0; i < rsMetaDataLen; i++) {
if(rsMetaData[i].colname ==columnName)
colCaption=rsMetaData[i].colcaption;
}
return colCaption;
}
function getSchemeArray(schemeName)
{
var schemeArray=new Array();
switch (schemeName) {
case "abgrp":
/*Bachelor: BA blau #374ca und 80 % , LA BA #5e70ba
Master: #64a6d9 #8cb7e1
Promotion: #7aa2ba
Sonstige: #98b4c9*/
schemeArray=['#374ca','#5e70ba','#64a6d9','#8cb7e1','#7aa2ba','#98b4c9','#ff933e'];
break;
case "fak":
schemeArray=['#488a7c','#374ca9','#ffd705','#a68eca','#e84035','#64a6d9','#ff933e','#ee79ad','#7aa2ba','#c3df35','#9bceab','#782f88','#96BFFF'];
break;
case "unique":
schemeArray=['#004c93'];
break;
case "dichotom":
schemeArray=['rgb(97,162,124)','#c3df35','#9d96f5','#e7bcf3'];
break;
case "quadroColor":
schemeArray=['#374ca9','#5e70ba','#8794cb','#afb7dc'];
break;
case "blandLocalized":
myBland=9;
for(var j=0;j < 17;j++)
{
if(j==myBland)
schemeArray[j]='#004c93';
else
schemeArray[j]='#666666';
}
break;
case "colorGrades":
//cooles Tool:https://mdigi.tools/lighten-color/ in 7% Schritten heller
schemeArray=['#374ca9','#3c53b8','#455cc3','#556ac8','##6477cc','#7384d1','#8291d6','#919fdb','#a0ace0','#afb9e5','#bec6ea','#cdd4ef','#dce1f4','#eceef9','#f4f6fb','#f6f7fc'];
break;
default:
schemeArray=[
'#ec7206',
'#61a27c',
'#b8103b',
'#feca00',
'#FFDB5C',
'#ff9f7f',
'#fb7293',
'#E062AE',
'#E690D1',
'#e7bcf3',
'#9d96f5',
'#8378EA',
'#96BFFF'
];
break;
}
return schemeArray;
}
function openDashboardTab(tabnr,maskennr,optional_filter_name,optional_filter_value,myOptionalFilters)
{
var myForm=document.forms["Weiterverarbeitung"];
myForm.elements["tid"].value=maskennr;
myForm.elements["Tabnr."].value=tabnr;
myForm.elements["reuseresult"].value="false";
//zuerst alle Filter resetten:
if(myForm.elements["Booklet-Stylesheet"])
{
myForm.elements["Booklet-Stylesheet"].value="";
}
if(myOptionalFilters.length>0)
{
for(var j=0;j < myOptionalFilters.length;j++)
{
var optionalFilterFldName=myOptionalFilters[j+1];
console.log("Resetting "+optionalFilterFldName);
if(myForm.elements[optionalFilterFldName])
{
myForm.elements[optionalFilterFldName].value="";
}
}
}
if(optional_filter_name != "")
{
myForm.elements[optional_filter_name].value=optional_filter_value;
}
myForm.submit();
}
function openKachelDetails(ergebniselementOrdnr,formName,maskeninfoTID,grafikUniquename,tablestylesheet,reuseResults)
{
document.forms[formName].elements["tid"].value=maskeninfoTID;
document.forms[formName].elements["Grafik"].value=grafikUniquename;
document.forms[formName].elements["tablestylesheet"].value=tablestylesheet;
if(document.forms[formName].elements["##line##"])
{
document.forms[formName].elements["##line##"].value="";
}
if(!reuseResults)
{
document.forms[formName].elements["reuseresult"].value="false";
}
document.forms[formName].target="_blank";
document.forms[formName].submit();
}
function exportVizBooklet(contenttype,stylesheet)
{
document.forms['Weiterverarbeitung'].stylesheet.value = stylesheet;
//document.forms['Weiterverarbeitung'].tablestylesheet.value = stylesheet;
document.forms['Weiterverarbeitung'].contenttype.value = contenttype;
document.forms['Weiterverarbeitung'].target = '_blank';
document.forms['Weiterverarbeitung'].submit();
}
function numberFormatter(value,axisType,digits,usedLocale)
{
//TODO: digits auswerten
if(axisType=="value")
{
var myusedLocale="de-DE"; //default
if(!usedLocale || usedLocale=="")
myusedLocale=usedLocale;
return new Intl.NumberFormat(myusedLocale).format(value);
}
else
return value ;
}
function closeModalCard(elemId)
{
var myModalCard=document.getElementById(elemId);
myModalCard.classList.remove('is-active');
}
function toggleSideBarDiv(mySidebarDivId)
{
//first close all divs in the sidebar except the one seleced:
const allSidebarDivs = document.getElementsByClassName("sidebar");
for (let i = 0; i < allSidebarDivs.length; i++) {
if(allSidebarDivs[i].id!=mySidebarDivId)
allSidebarDivs[i].style.display="none";
}
//now toggle:
var myDiv=document.getElementById(mySidebarDivId);
if(myDiv.style.display=="block")
{
myDiv.style.display="none";
myDiv.classList.remove("sidebar");
}
else
{
myDiv.style.display="block";
myDiv.classList.add("sidebar");
}
}
function prettifyJson(srcCode)
{
var ret="";
ret=srcCode.replace(/],/g,"],\n");
ret=ret.replace(/},/g,"},\n");
return ret;
}
function pivotTable1(rsData,rsMetaData,srcColNr)
{
rsData.forEach((row) => {
for (var col in row) {
console.log(col +"-"+row[col]);
}
}
);
}
function pivotTable(rsData,rsMetaData,srcColNrStart)
{
var rsDataPivot=new Array();
var nrSourceRows=rsData.length;
var nrSouceCols=rsMetaData.length;
var rsRow=new Array();
var zs="";
var targetRownr=0;
//first line will have headers:
var rownr=0;
zs+="Zeile|";
rsRow[rownr]="Zeile";
rownr++;
rsData.forEach((row) => {
var colnr=0;
for (var col in row) {
if(colnr==srcColNrStart)
{
zs+=row[col]+"|";
rsRow[rownr]=row[col];
}
colnr++;
}
rownr++;
}
);
zs +="\n";
targetRownr++;
rsDataPivot.push(rsRow);
//now the data:
var metaDataColnr=0;
rsMetaData.forEach((col) => {
if(metaDataColnr>srcColNrStart && col.colcaption.trim()!="")
{
//start a new row:
var rsRow=new Array();
var colname=col.colname;
zs+=col.colcaption +"|";
rsRow[0]=col.colcaption;
var targetColnr=1;
var rownr=0;
rsData.forEach((row) => {
var colnr=0;
for (var col in row) {
if(colnr==metaDataColnr)
{
zs+=row[col]+"|";
rsRow[targetColnr]=row[col];
targetColnr++;
}
colnr++;
};
rownr++;
});
zs+="\n";
rsDataPivot.push(rsRow);
}
metaDataColnr++;
});
//alert(zs);
/* for(var row=0;row < nrSourceRows;row++)
{
rsRow[row]=rsData[row][srcColNr];
}
rsDataPivot.push(rsRow);
//Now line 2 upwards:
rsData.forEach((row) => {
for (var col in row) {
console.log(col +"-"+row[col]);
}
}
);
}
for(var col=srcColNr+1;col < nrSouceCols;col++)
{
var rsRow=new Array();
var srcColCounter=0;
//first targetcolumn has name
rsRow[0]=rsMetaData[col];
for(var row=0;row < nrSourceRows;row++)
{
rsRow[row+1]=rsData[row][col];
}
rsDataPivot.push(rsRow);
}
console.log(rsDataPivot);
*/
return rsDataPivot;
}