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
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¶ms="+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; |
|
}
|
|
|