Skip to content

Instantly share code, notes, and snippets.

@induprasad
Created May 3, 2018 12:53
Show Gist options
  • Save induprasad/28c8a5fa39167d9d6d517f810478e9b3 to your computer and use it in GitHub Desktop.
Save induprasad/28c8a5fa39167d9d6d517f810478e9b3 to your computer and use it in GitHub Desktop.
Helper of LCMP_StrikeChart component
({
//Function which draws the bar chart
barChart: function (component, helper) {
component.set('v.displayAxis', true);
var dataset = component.get("v.data"); //The data retrieved from the controller or parent component
var color = helper.getColors(); //Setting the colors to the bars
//Setting the orientation of the chart as vertical, can also be turned to horizontal
var isVertical = component.get('v.orientation') === 'vertical';
var numericalAxis = isVertical ? 'y' : 'x';
var stringAxis = isVertical ? 'x' : 'y';
//Setting the labels for the X & Y axis
var xAxisLabel = component.get('v.xAxisLabel');
var yAxisLabel = component.get('v.yAxisLabel');
//Setting the height and width of the chart
var chartWidth = component.get('v.containerWidth');
var chartHeight = helper.getHeight(chartWidth);
helper.setyAxisLabelMaxHeight(component, chartHeight);
var paddingBox = helper.getPaddingBox(chartWidth);
var leftAxis = component.find('leftAxis').getElement();
$A.util.removeClass(leftAxis, 'slds-hide');
var leftAxisLabelWidth = leftAxis.clientHeight; //get height since we rotated
chartWidth -= leftAxisLabelWidth;
var x0 = d3.scaleBand().rangeRound([0, chartWidth]).paddingInner(0.1);
var x1 = d3.scaleBand().padding(0.05);
var y = d3.scaleLinear().rangeRound([chartHeight, 0]);
//Setting the formats of the numbers and the strings
var numericalFormat = function (d) {
return helper.abbreviateNumber(d)
};
var stringFormat = function (d) {
return d;
};
var xTickFormatter = stringFormat;
var yTickFormatter = numericalFormat;
//Creating the values on both the axis
var xAxis = helper.addBottomAxis(x0, 0, xTickFormatter);
var yAxis = helper.addLeftAxis(y, 0, yTickFormatter);
var svg = d3.select(component.find('chart').getElement()).append("svg")
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr('style', 'transform: translateX(' + (leftAxisLabelWidth) + 'px);');
//Here we pass the chart related data from the LCMP_CaseTrackerCharts component as a wrapper object
//The options variable below stores all the fields from the wrapper except the label/Account field
var options = d3.keys(dataset[0]).filter(function(key) { return key !== "label"; });
//Looping through each element of the data from parent and getting its name and corresponding value
dataset.forEach(function(d) {
d.valores = options.map(function(name) { return {name: name, value: +d[name]}; });
});
//X0 is the chart element, X1 is each bar in the chart
x0.domain(dataset.map(function(d) { return d.label; }));
x1.domain(options).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(dataset, function(d) { return d3.max(d.valores, function(d) { return d.value; }); })]);
//The functions which create the html to form the bar chart
svg.append("g")
.attr("class", "x sc-axis")
.attr("transform", "translate(0," + chartHeight + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y sc-axis")
.call(yAxis);
//Drawing each bar and drawing it as per its label and positioning it appropriately
var bar = svg.selectAll(".sc-bc-bar")
.data(dataset)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d.label) + ",0)"; });
//Settig the x position and v position of each bar relative to the previous bar
bar.selectAll(".sc-bc-bar")
.data(function(d) { return d.valores; })
.enter().append("rect").attr('class', 'sc-bc-bar')// drawing a rectangle and appending required styling
.attr("width", x1.bandwidth()) // setting the width of each bar
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("value", function(d){return d.name;})
.attr("height", function(d) { return chartHeight - y(d.value); }) // setting the height of the chart
.style("fill", function(d) { return color(d.name); }); // filling the color for the bar
//While hovering over each bar, the corresponding data values are displayed in the tooltip
bar.on('mouseover', $A.getCallback(function (dataPoint) {
var x = dataPoint.label;
var elements = document.querySelectorAll(':hover');
var l = elements.length;
l = l-1;
var elementData = elements[l].__data__;
var elementLabel = elementData.name;
if(elementLabel==="OpenCases"){
elementLabel = "Open Cases";
}
else if(elementLabel==="ClosedCases"){
elementLabel = "Closed Cases";
}
else if(elementLabel==="TotalCases"){
elementLabel = "Total Cases";
}
var y = elementLabel +" - "+elementData.value;
// Setting the format of the tooltip
var tooltipHtml = '<span class="sc-axis-label">' + xAxisLabel + ': </span><span class="sc-axis-value">' + x + '</span><br/>' +
'<span class="sc-axis-label">' + yAxisLabel + ': </span><span class="sc-axis-value">' + y + '</span>';
component.set('v.tooltipHtml', tooltipHtml)
}));
//Hide tooltip after the mouse moves out
bar.on('mouseout', $A.getCallback(function () {
helper.hideTooltip(component);
}));
//Get the position of the mouse relative to the chart
bar.on('mousemove', $A.getCallback(function (dataPoint) {
var mousePos = d3.mouse(component.find('chartContainer').getElement());
var tooltipOptions = {
x: mousePos[0],
y: mousePos[1],
chartWidth: chartWidth
}
helper.showToolTip(component, tooltipOptions);
}));
//Setting the legend for the chart (legend is the indicator which helps to determine which color represents what number)
var legend = svg.selectAll(".legend")
.data(options.slice())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
//Creating the rectangle for the legend
legend.append("rect")
.attr("x", chartWidth + 76)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
//Creating the text for the legend
legend.append("text")
.attr("x", chartWidth + 70)
.attr("y", 9)
.attr("dy", ".35em")
.attr("style", "font-size: .625rem;color: #8b8b8b;text-anchor: end")
.text(function(d) {
if(d === "OpenCases") {
d = "Open Cases";
} else if(d === "ClosedCases") {
d = "Closed Cases";
}
else if(d === "TotalCases") {
d = "Total Cases";
}
return d;
});
},
//Sets the maximum value for the Y axis
setyAxisLabelMaxHeight: function (component, chartHeight) {
component.set('v.yAxisLabelMaxHeight', chartHeight * .7);
},
// Funtion to hide the tooltip box
hideTooltip: function(component) {
component.set('v.tooltipOpacity', 0);
component.set('v.tooltipDisplay', 'none')
},
//Function to set the tooltip position and data
showToolTip: function(component, tooltipOptions) {
var tooltipElement = component.find('tooltipContainer').getElement()
var tooltipElementCopy = component.find('tooltipContainerCopy').getElement();
var tooltipOffSet = 10;
var tooltipXPos = tooltipOptions.x + tooltipOffSet;
var tooltipYPos = tooltipOptions.y + tooltipOffSet;
if ((tooltipElementCopy.clientWidth + tooltipXPos) > tooltipOptions.chartWidth) {
tooltipXPos -= (tooltipElementCopy.clientWidth + (tooltipOffSet * 2));
if (tooltipXPos < 0) {
tooltipXPos = tooltipOptions.x + tooltipOffSet;
}
}
component.set('v.tooltipDisplay', 'block');
component.set('v.tooltipXPos', tooltipXPos);
component.set('v.tooltipYPos', tooltipYPos);
component.set('v.tooltipOpacity', 1);
},
//Function which sets the padding for the chart
getPaddingBox: function(chartWidth) {
return {
top: chartWidth * .02,
left: chartWidth * .1,
bottom: chartWidth * .1,
right: chartWidth * .02
}
},
//Function which sets the colors for the bars
getColors: function() {
return d3.scaleOrdinal().range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c",
"#ff8c00", "#8cc5aa", "#9fa0a4", "#16325c", "#76ded9", "#08a69e",
"#e2cd81", "#e49e24", "#c03a38"]);
},
//Function which rounds off the bar value
abbreviateNumber: function(amount) {
var absAmount = Math.abs(Number(amount));
var amountNumber = Number(amount);
var shortenedNumber = amountNumber;
var abbreviation = '';
var trillion = Math.pow(10, 12);
var billion = Math.pow(10, 9);
var million = Math.pow(10, 6);
var thousand = Math.pow(10, 3);
if (absAmount / trillion >= 1) {
shortenedNumber = amountNumber / trillion;
abbreviation = 'T';
} else if (absAmount / billion >= 1) {
shortenedNumber = amountNumber / billion;
abbreviation = 'B';
} else if (absAmount / million >= 1) {
shortenedNumber = amountNumber / million;
abbreviation = 'M';
} else if (absAmount / thousand >= 1) {
shortenedNumber = amountNumber / thousand;
abbreviation = 'K';
}
return (parseFloat(shortenedNumber.toFixed(1)) + abbreviation);
},
addLeftAxis: function(scale, tickSizeOuter, tickFormat) {
return d3.axisLeft().scale(scale).tickSizeOuter(tickSizeOuter).tickFormat(tickFormat);
},
addBottomAxis: function(scale, tickSizeOuter, tickFormat) {
return d3.axisBottom().scale(scale).tickSizeOuter(tickSizeOuter).tickFormat(tickFormat);
},
getWidth: function(basedOnWidth) {
return basedOnWidth * .75;
},
getHeight: function(basedOnWidth) {
return basedOnWidth * .66;
},
//Function to determine the font size of the chart based on chart width
determineFontSize: function(chartWidth) {
var fontSize = '.8125rem';
if (chartWidth < 767) {
fontSize = '.625rem';
} else if (chartWidth < 1023) {
fontSize = '.75rem';
}
return fontSize;
},
//Function which performs the drawing of the chart
drawChart: function(component, helper) {
var chartType = component.get('v.type');
var chartToDraw = chartType + 'Chart';
if (chartType === 'pie' || chartType === 'donut') chartToDraw = 'pieDonutChart';
helper[chartToDraw](component, helper);
component.set('v.chartRendered', true);
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment