/* * Class NVD3CustomGraphs * * @elementId - the html DOM id * * Requires nv.d3.js, d3.v2.js */ var NVD3CustomGraphs = function() { function drawPiechart(datum, elementId, graphOptions, onClick) { //console.log(datum[0]); totalValue = datum[0].values.reduce(function(a, b) { return (a + graphOptions.getValue(b)); }, 0); if ((datum[0].values.length < 1) || (totalValue == 0)) { cleanGraph(elementId); return; } datum[0].values = datum[0].values.filter(function(d) { d.disabled = false; // for re-enabling the legend return (graphOptions.getValue(d)); // filter out the 0 values }); if (graphOptions.sortByValueDesc) { datum[0].values = datum[0].values.sort(function(a, b) { return (graphOptions.getValue(a) < graphOptions.getValue(b)) ? 1 : -1; }); } if (graphOptions.getSortingValueAsc) { datum[0].values = datum[0].values.sort(function(a, b) { return (graphOptions.getSortingValueAsc(a) < graphOptions.getSortingValueAsc(b)) ? -1 : 1; }); } // Construct the chart data in a format that nvd3 understands nv.addGraph({ generate: function() { var chart = nv.models.pieChart() .x(function(d) { return graphOptions.getName(d); }) .y(function(d) { return graphOptions.getValue(d); }) .showLabels(true) .pieLabelsOutside(graphOptions.pieLabelsOutside) .labelSunbeamLayout(graphOptions.labelSunbeamLayout) .showLegend(graphOptions.legend) .donut(graphOptions.donut) .donutLabelsOutside(graphOptions.donutLabelsOutside) .margin({top: 0, right: graphOptions.lrMargin, bottom: 0, left: graphOptions.lrMargin}) .tooltipContent(function(key, y, e, graph) { if (graphOptions.tooltipContent) return graphOptions.tooltipContent(key, y, e, graph); else { var sum = d3.sum(graph.container.__data__[0].values, function(d) { return (!d.disabled) ? graphOptions.getValue(d) : 0; }); var metadata = graph.container.__data__[0].metadata; // Use e.value instead of y, y is a formated string and parsing to number fails var percentage = ((e.value/sum)*100).toFixed(2); var unit = (metadata && metadata.unit) ? metadata.unit : graphOptions.unit; return "

" + key + "

" + "

" + commasFixed2(e.value) + " " + unit + " - " + percentage + "%" + "
" + " (of " + commasFixed2(sum) + " " + unit +")" + "

"; } }); /* Add on click events */ var svg = d3.select("#" + elementId + " svg"); if (onClick && !graphOptions.clickFiltersMap) { svg.classed("clickable", true); chart.pie.dispatch.on("elementClick", function(e) { var color; svg.selectAll(".nv-slice").each(function(d, i) { if (i === e.index) { color = d3.select(this).attr("fill"); e["color"] = color; return; } }); onClick(e); }); } if (graphOptions.clickFiltersMap && graphOptions.showOnMap && graphOptions.showOnMap(datum[0].metadata)) { svg.classed("clickable", true); chart.pie.dispatch.on("elementClick", function(e) { drawMap(reportOptions.hasDetailedMap, graphOptions.getMapObjects([e.point])); if (onClick) // forward the other click event onClick(e); }); } svg.datum(datum) .transition() .duration(config.transitionDuration) .call(chart); nv.utils.windowResize(chart.update); //nv.utils.windowResize(updateChartHeight); nv.utils.windowResize(function() { if (graphOptions.legend) { decorateKeys(elementId); } if (datum[0].key) { if (graphOptions.donut) drawDonutLabel(elementId, datum[0].key) else drawPieLabel(elementId, datum[0].key) } }); //svg.select(".nv-pie") // .attr("filter", "url(#dropShadow)"); return chart; }, callback: function() { applyDefaultStyle(elementId); if (graphOptions.legend) { decorateKeys(elementId); } if (datum[0].key) { if (graphOptions.donut) drawDonutLabel(elementId, datum[0].key) else drawPieLabel(elementId, datum[0].key) } var svg = d3.select("#" + elementId + " svg"); if (graphOptions.showOnMap && graphOptions.showOnMap(datum[0].metadata)) { if (!graphOptions.mapKeepColours) { svg.selectAll(".nv-slice").each(function(d, i) { datum[0].values[i]["Colour"] = d3.select(this).attr("fill"); }); } //else // datum[0].values.map(function(d) { d["Colour"] = ""; return d;); if (graphOptions.drawMapByDefault && graphOptions.getMapObjects(datum[0].values)) drawMap(reportOptions.hasDetailedMap, graphOptions.getMapObjects(datum[0].values)); } }, }); } 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) .attr("fill", "#999999") .style("font-family", "Chalet-LondonSixty") .style("font-size", "20px") .style("line-height", "18px"); } 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) .attr("fill", "#999999") .style("font-family", "Chalet-LondonSixty") .style("font-size", "14px") .style("line-height", "14px"); } 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/2) .attr("ry", margin/2) .attr("pointer-events", "none") .attr("fill", "transparent") .attr("stroke", "#aaa") .attr("stroke-width", "1px") .attr("stroke-opacity", "1") }; function applyDefaultStyle(elementID) { var svg = d3.select("#" + elementID + " svg"); svg.selectAll("g.nv-slice text") .attr("stroke", "none") .attr("stroke-width", "0") .style("font-size", "smaller"); svg.selectAll("g.nv-bar text") .attr("fill", "#000000") .attr("stroke", "none") .attr("stroke-width", "0") .style("font-size", "smaller") svg.selectAll("g.nv-slice rect") .style("fill", "transparent") .style("stroke", "none") .attr("stroke-width", "0") svg.selectAll("g.nv-axis path") .attr("stroke", "#000000") .attr("stroke-width", "1") } function drawMap(elementId, dataObjects) { map.show(); map.removeOverlay(); map.drawCircles(dataObjects, mapDataFunctions); $("#export-map").remove(); $("#content-description").append( $("") .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.breakdown.getValue(d); }, getX: function(d) {return reportOptions.mapGetX(d); }, getY: function(d) {return reportOptions.mapGetY(d); }, //getX: function(d) {return d.StartCoordinates.X; }, //getY: function(d) {return d.StartCoordinates.Y; }, getColour: function(d) {return d.Colour;}, getTooltipContent: reportOptions.mapTooltipContent, } function drawHorizBarchart(datum, elementId, graphOptions, onClick) { if (graphOptions.sortByValueDesc) { datum[0].values.sort(function(a, b) { return (graphOptions.getValue(a) < graphOptions.getValue(b)) ? 1 : -1; }); } if (graphOptions.getSortingValueAsc) { datum[0].values = datum[0].values.sort(function(a, b) { return (graphOptions.getSortingValueAsc(a) < graphOptions.getSortingValueAsc(b)) ? -1 : 1; }); } nv.addGraph({ generate: function() { var chart = nv.models.multiBarHorizontalChart() .x(function(d) { return graphOptions.getName(d); }) .y(function(d) { return graphOptions.getValue(d); }) .margin({top: 20, right: 20, bottom: 50, left: graphOptions.leftMargin}) .showValues(true) .tooltips(false) .showControls(false) .showLegend(false); chart.yAxis .axisLabel(graphOptions.getYLabel(datum[0])) .tickFormat(d3.format(".02f")); d3.select("#" + elementId + " svg") .datum(datum) .transition() .duration(config.transitionDuration) .call(chart); nv.utils.windowResize(chart.update); return chart; }, callback: function() { applyDefaultStyle(elementId); if (graphOptions.matchColoursFromPieElement) { matchColours(graphOptions.matchColoursFromPieElement, elementId); } if (graphOptions.addUnitsToBarchart) { addUnitsToBarchart(elementId, graphOptions.unit); } } }); } function matchColours(piechartID, barchartID) { var colours = []; d3.select("#" + piechartID + " svg").selectAll(".nv-slice").each(function(d, i) { colours.push(d3.select(this).attr("fill")); }); d3.select("#" + barchartID + " svg").selectAll(".nv-bar").each(function(d, i) { d3.select(this).attr("fill", colours[i]); d3.select(this).attr("stroke", "none"); }); } function addUnitsToBarchart(barchartID, unit) { d3.select("#" + barchartID + " svg").selectAll(".nv-bar text").each(function(d, i) { var originalText = d3.select(this).text(); d3.select(this).text(function() { return (unit.trim() == "$") ? (unit + originalText) : (originalText + unit); }); }); } return { drawPiechart: drawPiechart, drawHorizBarchart: drawHorizBarchart, }; };