Files
2025-09-29 00:52:08 +02:00

575 lines
18 KiB
JavaScript
Executable File

// reportOptions variable comes from respective config file
//var defaultFilterText = "type text to filter the chart";
// Array that stores objects for each element returned via rest
var chartsData;
var map;
var commasFixed2 = function(d) {return d3.format(",")(d.toFixed(2)); };
//var clickablePieChartLegend = "Pie Chart :: ";
//var detailedPieChartLegend = "Pie Chart :: ";
var clickableDOMId = "clickable-piechart";
var detailedDOMId = "detailed-piechart";
var lastSliceClicked = null;
function initPage() {
// function from generic.js, variable from config file
initHeaderAndFilters(headerAndFilters);
$("#content-body")
.append(
$("<div>").attr("id", clickableDOMId)
)
.append(
$("<div>").attr("id", detailedDOMId)
);
initSvg(clickableDOMId);
if (reportOptions.hasFriendlierNames) {
$("#content")
.append(
$("<div>")
.attr("id", "friendlier-names-field")
.append(
$("<input>")
.attr("id", "friendlier-names")
.attr("type", "checkbox")
.attr("disabled", false)
.prop("checked", true)
)
.append(
$("<label>")
.attr("for", "friendlier-names")
.attr("title", "Check to Switch to Friedlier Names")
.text("Friendlier Names")
.click(function() {
if (chartsData)
drawCharts();
})
)
);
}
if (reportOptions.hasDetailedMap) {
$("#" + detailedDOMId).parent().append(
$("<div>")
.attr("id", reportOptions.hasDetailedMap)
.addClass("hidden")
);
map = new SVGMap(reportOptions.hasDetailedMap, project.map);
map.hide();
}
updateWidth();
$("#filter").click(function() {
generateCharts();
});
//updateChartHeight();
generateCharts();
}
function generateCharts() {
chartsData = [];
// get the social club header filtering parameter values, headerAndFilters.headerType comes from local conf
var pValues = config.headerOptions[headerAndFilters.headerType].getParamValues();
if (reportOptions.hasExtraRestParams) {
$.each(reportOptions.hasExtraRestParams, function(i, paramObj) {
var value;
if (typeof paramObj.value === "function") {
value = paramObj.value();
}
else
value = paramObj.value;
pValues.Pairs[paramObj.key] = value;
});
}
if (reportOptions.hasDualEndpoints) {
var req = new ReportRequest(null, "json", null, config.restHost + config.reportsQueryAsync);
var endpointObject1 = {
restUrl: config.restHost + reportOptions.restEndpoint,
restAsyncUrl: config.restHost + reportOptions.restEndpointAsync,
pValues: [pValues],
}
var endpointObject2 = {
restUrl: config.restHost + reportOptions.restEndpoint2,
restAsyncUrl: config.restHost + reportOptions.restEndpoint2Async,
pValues: [pValues],
}
if ($("select#game-types option:eq(0)").is(":selected") && !$("select#game-types option:eq(1)").is(":selected")) {
req.sendMultipleAsyncRequest([endpointObject1], reportOptions.handleResults);
}
else if (!$("select#game-types option:eq(0)").is(":selected") && $("select#game-types option:eq(1)").is(":selected")) {
req.sendMultipleAsyncRequest([endpointObject2], reportOptions.handleResults);
}
else if ($("select#game-types").val() != null) {
if ($("select#game-types").val().length == 2) {
req.sendMultipleAsyncRequest([endpointObject1, endpointObject2], reportOptions.handleResults);
}
}
else if (!$("select#game-types").val()) {
req.sendMultipleAsyncRequest([endpointObject1, endpointObject2], reportOptions.handleResults);
}
} // End of if has dual end-points
else {
var req = new ReportRequest(config.restHost + reportOptions.restEndpoint,
"json",
config.restHost + reportOptions.restEndpointAsync + pValues.ForceUrlSuffix,
config.restHost + config.reportsQueryAsync);
req.sendSingleAsyncRequest(pValues, drawCharts);
}
} //end of generateCharts()
function cleanCharts() {
cleanGraph(clickableDOMId);
cleanDetailedChart();
// Unbind onResize event
if (typeof window.onresize === "function")
window.onresize = null;
//console.log(window.onresize);
}
function cleanDetailedChart() {
$("#" + detailedDOMId).hide("fade", {}, "normal");
$("#" + detailedDOMId).find("div").each(function() {
//console.log($(this).attr("id"));
cleanGraph($(this).attr("id"));
lastSliceClicked = null;
});
//cleanGraph(detailedDOMId);
if (map)
map.hide();
}
/*
function updateChartHeight() {
// Adjust the height of the charts automatically
//var windowHeight = $("#content").height() - 40;
var windowHeight = $("#content").height() - 2 * $("#sub-header").height();
$("#" + clickableDOMId).css("height", windowHeight);
$("#" + detailedDOMId).css("height", windowHeight);
if (reportOptions.hasDetailedMap)
$("#" + reportOptions.hasDetailedMap).css("height", windowHeight);
}
*/
function updateWidth() {
if (reportOptions.hasDetailedMap) {
//if ($(window).width() > 1366) {
$("#" + clickableDOMId).css("width", "33%");
$("#" + detailedDOMId)
.css("width", "33%")
//.css("left", "33%");
$("#" + reportOptions.hasDetailedMap)
.css("width", "33%")
//.css("left", "66%");
//}
//else {
// $("#" + clickableDOMId).css("width", "455");
// $("#" + detailedDOMId)
// .css("width", "455")
// .css("left", "455px !important");
// $("#" + reportOptions.hasDetailedMap)
// .css("width", "455")
// .css("left", "910px !important");
//}
}
}
function drawCharts(data) {
//cleanDetailedChart();
//$("#detailed-piechart").hide("fade", {}, "normal");
// If a processFunction function is specified
if (data) {
if (reportOptions.processFunction)
chartsData = reportOptions.processFunction(data);
else
chartsData = data;
}
totalValue = chartsData.reduce(function(a, b) { return (a + reportOptions.getValue(b)); }, 0);
//console.log(totalValue);
if ((chartsData.length < 1) || (totalValue == 0)) {
cleanCharts();
Sexy.alert(config.noDataText);
return;
}
/*
var filterText = $("#chart-filter-input").val();
if (filterText == defaultFilterText)
filterText = "";
var re = new RegExp(filterText, "i");
// create an array that will store the filtered chart data
var filteredArray = [];
// loop to each element's data
$.each(chartsData, function(i, chartData) {
// match the name with the input filter text
if (re.test(reportOptions.getName(chartData))) {
// for each chart type, populate its array with the predefined functions over the data
chartData["Name"] = reportOptions.getName(chartData);
chartData["Value"] = reportOptions.getValue(chartData);
filteredArray.push(chartData);
}
});
if (filteredArray.length < 1) {
//console.log("Nothing matched for '" + filterText + "'");
cleanCharts();
return;
}
filteredArray.sort(function(a, b) { return (a.Value > b.Value) ? -1 : 1});
//console.log(filteredArray);
// Construct the chart data in a format that nvd3 understands
var datum = [{
values: filteredArray,
}];
*/
var datum = [{
values: chartsData
.filter(function(d) {
d.disabled = false; // for re-enabling the legend
return reportOptions.getValue(d) > 0; // filter out the 0 values
})
.sort(function(a, b) {
return ((reportOptions.getValue(a) > reportOptions.getValue(b)) ? -1 : 1);
}),
}];
nv.addGraph({
generate: function() {
var chart = nv.models.pieChart()
.x(function(d) { return reportOptions.getName(d); })
.y(function(d) { return reportOptions.getValue(d); })
.showLabels(true)
.pieLabelsOutside(reportOptions.pieLabelsOutside)
.labelSunbeamLayout(reportOptions.labelSunbeamLayout)
.showLegend(reportOptions.legend)
.donut(reportOptions.donut)
.donutLabelsOutside(reportOptions.donutLabelsOutside)
.margin({top: 0, right: reportOptions.lrMargin, bottom: 0, left: reportOptions.lrMargin})
.tooltipContent(function(key, y, e, graph) {
if (reportOptions.tooltipContent)
return reportOptions.tooltipContent(key, y, e, graph);
else {
var sum = d3.sum(graph.container.__data__[0].values, function(d) {
return (!d.disabled) ? reportOptions.getValue(d) : 0;
});
// Use e.value instead of y, y is a formated string and parsing to number fails
var percentage = ((e.value/sum)*100).toFixed(2);
return "<h3>" + key + "</h3>"
+ "<p>" + commasFixed2(e.value) + " " + reportOptions.unit
+ " - " + percentage + "%" + "<br />"
+ " (of " + commasFixed2(sum) + " " + reportOptions.unit +")" + "</p>";
}
});
/* Add on click events */
chart.pie.dispatch.on("elementClick", function(e) {
//var detailedDataObject = chartsData[e.index] || chartsData[e.label];
//var detailedDataObject = filteredArray[e.index];
detailedDataObject = e.point;
lastSliceClicked = e.label;
if (reportOptions.hasDetailedData(detailedDataObject)) {
// console.log(e);
//$("#detailed-piechart legend")
// .html(detailedPieChartLegend
// + "<span id='detailed-metric'>"
// + reportOptions.detailedTitle
// + e.label
// + "</span>"
// );
$("#" + detailedDOMId).show("fade", {}, "normal");
drawDetailedChart(detailedDataObject);
}
//else {
// Sexy.alert("No detailed data available for " + e.label + ".");
// cleanDetailedChart();
//}
});
var svg = d3.select("#" + clickableDOMId + " svg");
svg.datum(datum)
.transition()
.duration(config.transitionDuration)
.call(chart);
nv.utils.windowResize(chart.update);
//nv.utils.windowResize(updateChartHeight);
nv.utils.windowResize(function() {
drawDonutLabel(clickableDOMId, reportOptions.title);
decorateKeys(clickableDOMId);
});
/*
svg.select(".nv-pie")
.attr("filter", "url(#dropShadow)");
*/
return chart;
},
callback: function() {
drawDonutLabel(clickableDOMId, reportOptions.title);
decorateKeys(clickableDOMId);
//console.log(lastSliceClicked);
if (lastSliceClicked) {
var availableLabels = datum[0].values.map(function(d) { return reportOptions.getName(d); });
var searchIndex = availableLabels.indexOf(lastSliceClicked);
if (searchIndex != -1) {
drawDetailedChart(datum[0].values[searchIndex]);
}
else {
// clean it cause the previous selected item is not available
cleanDetailedChart();
}
}
},
});
//$("#" + clickableDOMId + " legend").text(clickablePieChartLegend + reportOptions.title);
}
function drawDetailedChart(selectedObject) {
// Construct the chart data in a format that nvd3 understands
//var placeholderHeight = $("#" + detailedDOMId).height() - 2 * $("#" + detailedDOMId + " legend").height();
var placeholderHeight = $("#" + detailedDOMId).height();
var detailedColumns = 2;
var detailedObjects = reportOptions.getDetailedObjects(selectedObject);
// Clean not needed previous svg's
var existingItems = $("#" + detailedDOMId).find("div");
if (existingItems.length > detailedObjects.length)
existingItems.slice(detailedObjects.length).remove();
$.each(detailedObjects, function(i, detailedObject) {
var detailedPiechartDOMId = detailedDOMId + "_" + i;
// This will add the svg on the first time
if ($("#" + detailedDOMId).find("#" + detailedPiechartDOMId).size() == 0) {
$("#" + detailedDOMId)
.append(
$("<div>").attr("id", detailedPiechartDOMId)
);
initSvg(detailedPiechartDOMId);
}
$("#" + detailedPiechartDOMId)
.removeClass().addClass(function() {return (i%2) ? "float-right" : "float-left"})
.css("width", function() {
// give max width to the first element in odd number of detailed piecharts
return (((i==0) && (detailedObjects.length%2)) || (detailedObjects.length == detailedColumns))
? "100%" : Math.floor(100/detailedColumns) + "%";
})
.css("height",function() {
return (detailedObjects.length == detailedColumns)
? Math.floor(placeholderHeight/ Math.round(detailedObjects.length))
: Math.floor(placeholderHeight/ Math.round(detailedObjects.length / detailedColumns))
})
var pieItems = detailedObject.Items.sort(function(a, b) {
return (reportOptions.getDetailedValue(a) > reportOptions.getDetailedValue(b)) ? -1 : 1
});
var datum = [{
values: pieItems,
}];
var hasDetailedLabel = reportOptions.getDetailedLabel && reportOptions.getDetailedLabel(detailedObject);
nv.addGraph({
generate: function() {
var chart = nv.models.pieChart()
.x(function(d) { return reportOptions.getDetailedName(d); })
.y(function(d) { return reportOptions.getDetailedValue(d); })
.showLabels(true)
//.labelThreshold(.04)
.pieLabelsOutside((hasDetailedLabel) ? false : reportOptions.detailedPieLabelsOutside)
.labelSunbeamLayout(reportOptions.detailedLabelSunbeamLayout)
.showLegend(reportOptions.detailedLegend)
.donut((hasDetailedLabel) ? false : reportOptions.detailedDonut)
.donutLabelsOutside((hasDetailedLabel) ? false : reportOptions.detailedDonutLabelsOutside)
.margin({top: 0, right: reportOptions.lrMargin, bottom: 0, left: reportOptions.lrMargin})
.tooltipContent(function(key, y, e, graph) {
if (reportOptions.tooltipContent)
return reportOptions.tooltipContent(key, y, e, graph);
else {
var sum = d3.sum(graph.container.__data__[0].values, function(d) {
return reportOptions.getDetailedValue(d);
});
// Use e.value instead of y, y is a formated string and parsing to number fails
var percentage = ((e.value/sum)*100).toFixed(2);
return "<h3>" + key + "</h3>"
+ "<p>" + commasFixed2(e.value) + " " + reportOptions.unit
+ " - " + percentage + "%" + "<br />"
+ " (of " + commasFixed2(sum) + " " + reportOptions.unit +")" + "</p>";
}
});
var svg = d3.select("#" + detailedPiechartDOMId + " svg");
svg.datum(datum)
.transition()
.duration(config.transitionDuration)
.call(chart);
nv.utils.windowResize(chart.update);
nv.utils.windowResize(function() {
decorateKeys(detailedPiechartDOMId);
});
//nv.utils.windowResize(updateChartHeight);
return chart;
},
callback: function() {
decorateKeys(detailedPiechartDOMId);
var svg = d3.select("#" + detailedPiechartDOMId + " svg");
svg.selectAll(".detailed-label").remove();
if (hasDetailedLabel) {
drawPieLabel(detailedPiechartDOMId, reportOptions.getDetailedLabel(detailedObject));
nv.utils.windowResize(function() {
drawPieLabel(detailedPiechartDOMId, reportOptions.getDetailedLabel(detailedObject));
});
}
else {
drawDonutLabel(detailedPiechartDOMId, lastSliceClicked);
nv.utils.windowResize(function() {
drawDonutLabel(detailedPiechartDOMId, lastSliceClicked);
});
}
if (reportOptions.hasDetailedMap && !reportOptions.getDetailedLabel(detailedObject)) {
svg.selectAll(".nv-slice").each(function(d, i) {
//colours.push(d3.select(this).attr("fill"));
pieItems[i]["Colour"] = d3.select(this).attr("fill");
});
drawMap(reportOptions.hasDetailedMap, pieItems);
}
}
});
});
}
function drawDonutLabel(elementID, labelText) {
var svg = d3.select("#" + elementID + " svg");
svg.selectAll(".donut-label").remove();
var legendHeight = svg.select(".nv-legendWrap");
legendHeight = (legendHeight[0][0]) ? legendHeight[0][0].getBoundingClientRect().height : 0;
svg.append("svg:text")
.attr("class", "donut-label")
.attr("x", $("#" + elementID).width() / 2)
.attr("y", (($("#" + elementID).height() - legendHeight) / 2) + legendHeight/2)
.attr("text-anchor", "middle")
.attr("stroke", 5)
.text(labelText);
}
function drawPieLabel(elementID, labelText) {
var svg = d3.select("#" + elementID + " svg");
svg.selectAll(".pie-label").remove();
svg.append("svg:text")
.attr("class", "pie-label")
.attr("x", $("#" + elementID).width() / 2)
.attr("y", ($("#" + elementID).height() - 10))
.attr("dy", 6)
.attr("text-anchor", "middle")
.attr("stroke", 5)
.text(labelText);
}
function decorateKeys(elementID) {
$("#" + elementID + " .nv-legend rect").remove();
var legend = d3.select("#" + elementID + " svg")
.select("g.nv-legend g");
if (!legend[0][0])
return;
var bbox = legend[0][0].getBBox();
var margin = 5;
legend.append("svg:rect")
.attr("x", bbox.x - margin)
.attr("y", bbox.y - margin)
.attr("width", bbox.width + 2*margin)
.attr("height", bbox.height + 2*margin)
.attr("rx", margin)
.attr("ry", margin)
.attr("pointer-events", "none");
}
function drawMap(elementId, dataObjects) {
map.show();
map.removeOverlay();
map.drawCircles(dataObjects, mapDataFunctions);
$("#export-map").remove();
$("#content-description").append(
$("<input />")
.attr("type", "button")
.attr("id", "export-map")
.attr("name", "export-map")
.attr("title", "Export current viewport to png")
.val("Export Map to PNG")
.css("float", "right")
.addClass("red-button hand")
.click(map.exportToImage)
);
if ($.browser.msie)
$("#export-map")
.addClass("hidden");
}
var mapDataFunctions = {
getValue: function(d) {return reportOptions.getDetailedValue(d); },
getName: function(d) {return d.Name; },
getX: function(d) {return d.StartCoordinates.X; },
getY: function(d) {return d.StartCoordinates.Y; },
getColour: function(d) {return d.Colour;},
}