// Handling the browser onresize event
window.onresize = function () {
scope.$apply();
};
scope.render = function (data) {
var ageNames = d3.keys(data[0]).filter(function (key) {
return key !== "GateName" &&
key !== "QualityGateOrCheck" &&
key !== "GateId" &&
key !== "PercentOfCompletedByAllGates" &&
key !== "PercentOfCompletedByActiveGates" &&
key !== "PercentOfActiveByAllGates" &&
key !== "PercentageOfCompleteByAllGates" &&
key !== "PercentageOfCompleteByActiveGates" &&
key !== "PercentageOfActiveByAllGates" &&
key !== "PercentageOfCompleteByAllChecks" &&
key !== "PercentageOfCompleteByActiveChecks" &&
key !== "PercentageOfActiveByAllChecks";
});
data.forEach(function (d) {
d.ages = ageNames.map(function (name) { return { name: name, value: +d[name] }; });
});
var margin = { top: 20, right: 20, bottom: 30, left: 60 }, width = 1140 - margin.left - margin.right, height = 300 - margin.top - margin.bottom;
var ticks = [0, 25, 50, 75, 100];
var x0 = d3.scale.ordinal().rangeRoundBands([0, width - 160], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear().range([height, 0]);
var color = d3.scale.ordinal().range(["#3366cc", "#830300", "#97be0d"]);
var xAxis = d3.svg.axis().scale(x0).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left").tickValues(ticks);
var svg = d3.select("#barChart").append("svg").attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom).append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x0.domain(data.map(function (d) { console.log(d.GateName); return d.GateName; }));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function (d) { return d3.max(d.ages, function (d) { return d.value; }); })]);
svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
svg.append("g").attr("class", "y axis").call(yAxis).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", ".71em").style("text-anchor", "end").text("% Percentage");
var state = svg.selectAll(".state").data(data).enter().append("g").attr("class", "g").attr("transform", function (d) { return "translate(" + x0(d.GateName) + ",0)"; });
state.selectAll("rect").data(function (d) { return d.ages; }).enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function (d) { return x1(d.name); })
.attr("y", function (d) { return y(d.value); })
.attr("height", function (d) { return height - y(d.value); })
.style("fill", function (d) { return color(d.name); })
.each(function (d) { this._current = d; })
.on("mouseover", function (d) {
var xPosition = parseFloat(d3.select("rect").attr("x")) + x1.rangeBand() / 2;
var yPosition = parseFloat(d3.select("rect").attr("y")) / 2 + height / 2;
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.select("#toolipHeading, #value")
.text(d.name, d.value);
d3.select("#tooltip").classed("hidden", false);
}).on("mouseout", function () {
//Hide the tooltip
d3.select("#tooltip").classed("hidden", true);
});
state.selectAll("rect").data((function (d) { return d.ages; }))
.attr("id", function (d) { return d.name; })
.append("title");
var KPILegend = ["PercentageOfComplete/AllRequirements", "PercentageOfComplete/ActiveRequirements", "PercentageOfActive/AllRequirements"];
var legend = svg.selectAll(".legend")
.data(KPILegend.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect").attr("x", 900)
.attr("width", 15)
.attr("height", 15)
.style("fill", color)
.style('stroke', color)
.on('click', function (label) {
var svg1 = d3.select("#barChart");
svg1.selectAll('.g').selectAll('rect#PercentageOfCompleteByAllRequirements').style("display", 'block');
});
};
scope.$watch('data', function (chartDataNew, chartDataOld, attributes) {
if (chartDataNew != undefined && chartDataOld == undefined) {
if (scope.data != undefined) {
$("#barChart").empty();
scope.render(scope.data);
}
}
else if (chartDataNew != undefined && chartDataOld != undefined) {
var NewChartJSON = JSON.stringify(chartDataNew);
NewChartJSON = JSON.parse(NewChartJSON);
$.each(NewChartJSON, function (i, val) {
delete NewChartJSON[i].ages;
});
var OldChartJSON = JSON.stringify(chartDataOld);
OldChartJSON = JSON.parse(OldChartJSON);
NewChart = NewChartJSON;
var flag = false;
$.each(NewChart, function (index, dataNew) {
$.each(OldChartJSON, function (index, dataOld) {
if (dataNew.GateId == dataOld.GateId) {
if (dataNew.GateName != dataOld.GateName ||
dataNew.QualityGateOrCheck != dataOld.QualityGateOrCheck ||
dataNew.PercentageOfCompleteByAllRequirements != dataOld.PercentageOfCompleteByAllRequirements ||
dataNew.PercentageOfCompleteByActiveRequirements != dataOld.PercentageOfCompleteByActiveRequirements ||
dataNew.PercentageOfActiveByAllRequirements != dataOld.PercentageOfActiveByAllRequirements) {
flag = true;
}
}
});
});
if (flag == true) {
$("#barChart").empty();
scope.render(scope.data);
}
}
}, true);
}
};
This is a custom implementation of a grouped bar chart using d3.js. There are 3 items in the legends section. Clicking on a legend bar with the id "xyz" should toggle its visibility.
To achieve this functionality, the following code snippet can be used:
svg1.selectAll('.g').selectAll('rect#PercentageOfCompleteByAllRequirements').style("display", 'block');
The above code selects all bars with the specified ID and attempts to change their display property. However, there might be issues with the expected behavior not being achieved despite applying the style property successfully.
If you are facing any challenges with this implementation, please seek assistance from the community or support resources.