function groupBarChart(config) { function setReSizeEvent(data) { var resizeTimer; window.removeEventListener('resize', function () { }); window.addEventListener('resize', function (event) { if (resizeTimer !== false) { clearTimeout(resizeTimer); } resizeTimer = setTimeout(function () { $(data.mainDiv).empty(); drawgroupBarChartChart(data); clearTimeout(resizeTimer); }, 500); }); } drawgroupBarChartChart(config); setReSizeEvent(config); } function creategroupBarChartLegend(mainDiv, columnsInfo, colorRange) { var z = d3.scaleOrdinal() .range(colorRange); var mainDivName = mainDiv.substr(1, mainDiv.length); $(mainDiv).before("
"); var keys = Object.keys(columnsInfo); keys.forEach(function (d) { var cloloCode = z(d); $("#Legend_" + mainDivName).append("\  \ " + columnsInfo[d] + " \ "); }); } function drawgroupBarChartChart(config) { var data = config.data; var columnsInfo = config.columnsInfo; var xAxis = config.xAxis; var yAxis = config.yAxis; var colorRange = config.colorRange; var mainDiv = config.mainDiv; var mainDivName = mainDiv.substr(1, mainDiv.length); var label = config.label; var requireLegend = config.requireLegend; d3.select(mainDiv).append("svg").attr("width", $(mainDiv).width()).attr("height", $(mainDiv).height() * 0.9); var svg = d3.select(mainDiv + " svg"), margin = { top: 20, right: 20, bottom: 30, left: 40 }, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height") - margin.top - margin.bottom; var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); if (requireLegend != null && requireLegend != undefined && requireLegend != false) { $("#Legend_" + mainDivName).remove(); creategroupBarChartLegend(mainDiv, columnsInfo, colorRange); } var x0 = d3.scaleBand() .rangeRound([0, width]) .paddingInner(0.1); var x1 = d3.scaleBand() .padding(0.05); var y = d3.scaleLinear() .rangeRound([height, 0]); var z = d3.scaleOrdinal() .range(colorRange); var keys = Object.keys(columnsInfo); x0.domain(data.map(function (d) { return d[xAxis]; })); x1.domain(keys).rangeRound([0, x0.bandwidth()]); y.domain([0, d3.max(data, function (d) { return d3.max(keys, function (key) { return d[key]; }); })]).nice(); var element = g.append("g") .selectAll("g") .data(data) .enter().append("g") .attr("transform", function (d) { return "translate(" + x0(d[xAxis]) + ",0)"; }); var rect = element.selectAll("rect") .data(function (d, i) { return keys.map(function (key) { return { key: key, value: d[key], index: key + "_" + i + "_" + d[xAxis] }; }); }) .enter().append("rect") .attr("x", function (d) { return x1(d.key); }) .attr("y", function (d) { return y(d.value); }) .attr("width", x1.bandwidth()) .attr("data-index", function (d, i) { return d.index; }) .attr("height", function (d) { return height - y(d.value); }) .attr("fill", function (d) { return z(d.key); }); //CBT:add tooltips var self = {}; self.svg = svg; self.cssPrefix = "groupBar0_"; self.data = data; self.keys = keys; self.height = height; self.width = width; self.label = label; self.yAxis = yAxis; self.xAxis = xAxis; barTooltip.addTooltips(self); rect.on("mouseover", function () { var currentEl = d3.select(this); var index = currentEl.attr("data-index"); barTooltip.showTooltip(self, index); }); rect.on("mouseout", function () { var currentEl = d3.select(this); var index = currentEl.attr("data-index"); barTooltip.hideTooltip(self, index); }); rect.on("mousemove", function () { barTooltip.moveTooltip(self); }); var circleRadius = x1.bandwidth() * 0.4; var circles = element.selectAll("circle") .data(function (d) { var teamWiseData = keys.map(function (key) { return { key: key, value: d[key], circles: d["circle_" + key], over: d.over }; }); var dataObj = []; teamWiseData.forEach(function (teamData) { if (teamData.circles != undefined && teamData.circles != 0 && teamData.circles.length > 0) { teamData.circles.forEach(function (data, i) { var tempObj = {}; tempObj["key"] = teamData["key"]; tempObj["value"] = teamData["value"]; tempObj["circles"] = [data]; tempObj["over"] = teamData["over"]; tempObj["circleNumber"] = i; dataObj.push(tempObj); }); } else { teamData["circleNumber"] = 0; dataObj.push(teamData); } }); return dataObj; }) .enter().append("circle") .attr("cx", function (d) { return x1(d.key) + (x1.bandwidth() / 2); }) .attr("cy", function (d) { if ((y(d.value) - (circleRadius * 0.9)) - (d.circleNumber * (circleRadius * 2)) < 0) { return (y(d.value) + (circleRadius)) + (d.circleNumber * (circleRadius * 2)); } else { return (y(d.value) - (circleRadius * 0.9)) - (d.circleNumber * (circleRadius * 2)); } }) .attr("r", circleRadius)//x1.bandwidth() * 0.37) .attr("fill", "#fff") .attr("stroke", function (d) { return z(d.key); }) .attr("data", function (d) { var data = {}; data["over"] = d.over; data["runs"] = d.value; if (d.circles != undefined && d.circles.length > 0) { data["circles"] = d.circles } else { data["circles"] = []; } return JSON.stringify(data); }) .attr("stroke-width", "2px").attr("display", function (d) { if (d.circles == undefined || d.circles.length <= 0) { return "none"; } else { return "block"; } }); circles.on("mouseover", function () { var currentEl = d3.select(this); currentEl.attr("r", parseFloat(currentEl.attr("r")) + 1); var fadeInSpeed = 120; d3.select("#circletooltip_" + mainDivName) .transition() .duration(fadeInSpeed) .style("opacity", function () { return 1; }); d3.select("#circletooltip_" + mainDivName) .attr("transform", function (d) { var mouseCoords = d3.mouse(this.parentNode); var xCo = 0; if (mouseCoords[0] + 10 >= width * 0.80) { xCo = mouseCoords[0] - parseFloat(d3.selectAll("#circletooltipRect_" + mainDivName) .attr("width")); } else { xCo = mouseCoords[0] + 10; } var x = xCo; var yCo = 0; if (mouseCoords[0] + 10 >= width * 0.80) { yCo = mouseCoords[1] + 10; } else { yCo = mouseCoords[1]; } var x = xCo; var y = yCo; return "translate(" + x + "," + y + ")"; }); //CBT:calculate tooltips text var wicketData = JSON.parse(currentEl.attr("data")); var tooltipsText = ""; d3.selectAll("#circletooltipText_" + mainDivName).text(""); var yPos = 0; d3.selectAll("#circletooltipText_" + mainDivName).append("tspan").attr("x", 0).attr("y", yPos * 10).attr("dy", "1.9em").text(label.xAxis + ": " + wicketData.over); yPos = yPos + 1; d3.selectAll("#circletooltipText_" + mainDivName).append("tspan").attr("x", 0).attr("y", yPos * 10).attr("dy", "1.9em").text(label.yAxis + ": " + wicketData.runs); wicketData.circles.forEach(function (d, i) { yPos = yPos + 1; d3.selectAll("#circletooltipText_" + mainDivName).append("tspan").attr("x", 0).attr("y", yPos * 10).attr("dy", "1.9em").text(d["commentary"] + "(" + d.fall_of_wicket + ")"); }); //CBT:calculate width of the text based on characters var dims = helpers.getDimensions("circletooltipText_" + mainDivName); d3.selectAll("#circletooltipText_" + mainDivName + " tspan") .attr("x", dims.w + 2); d3.selectAll("#circletooltipRect_" + mainDivName) .attr("width", dims.w + 10) .attr("height", dims.h + 20); }); circles.on("mousemove", function () { var currentEl = d3.select(this); d3.selectAll("#circletooltip_" + mainDivName) .attr("transform", function (d) { var mouseCoords = d3.mouse(this.parentNode); var xCo = 0; if (mouseCoords[0] + 10 >= width * 0.80) { xCo = mouseCoords[0] - parseFloat(d3.selectAll("#circletooltipRect_" + mainDivName) .attr("width")); } else { xCo = mouseCoords[0] + 10; } var yCo = 0; if (mouseCoords[0] + 10 >= width * 0.80) { yCo = mouseCoords[1] + 10; } else { yCo = mouseCoords[1]; } var x = xCo; var y = yCo; return "translate(" + x + "," + y + ")"; }); }); circles.on("mouseout", function () { var currentEl = d3.select(this); currentEl.attr("r", parseFloat(currentEl.attr("r")) - 1); d3.select("#circletooltip_" + mainDivName) .style("opacity", function () { return 0; }); d3.select("#circletooltip_" + mainDivName).attr("transform", function (d, i) { // klutzy, but it accounts for tooltip padding which could push it onscreen var x = -500; var y = -500; return "translate(" + x + "," + y + ")"; }); }); //CBT:circle tooltips start var circleTooltipg = g.append("g") .attr("font-family", "sans-serif") .attr("font-size", 10) .attr("text-anchor", "end") .attr("id", "circletooltip_" + mainDivName) .attr("style", "opacity:0") .attr("transform", "translate(-500,-500)"); circleTooltipg.append("rect") .attr("id", "circletooltipRect_" + mainDivName) .attr("x", 0) .attr("width", 120) .attr("height", 80) .attr("opacity", 0.71) .style("fill", "#000000"); circleTooltipg .append("text") .attr("id", "circletooltipText_" + mainDivName) .attr("x", 30) .attr("y", 15) .attr("fill", function () { return "#fff" }) .style("font-size", function (d) { return 10; }) .style("font-family", function (d) { return "arial"; }) .text(function (d, i) { return ""; }); g.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x0)) .append("text") .attr("x", width / 2) .attr("y", margin.bottom * 0.9) .attr("dx", "0.32em") .attr("fill", "#000") .attr("font-weight", "bold") .attr("text-anchor", "start") .text(label.xAxis); g.append("g") .attr("class", "axis") .call(d3.axisLeft(y).ticks(null, "s")) .append("text") .attr("x", 0) .attr("y", 6) .attr("dy", "0.71em") .attr("fill", "#000") .attr("transform", "rotate(-90)") .attr("font-weight", "bold") .text(label.yAxis); } var helpers = { getDimensions: function (id) { var el = document.getElementById(id); var w = 0, h = 0; if (el) { var dimensions = el.getBBox(); w = dimensions.width; h = dimensions.height; } else { console.log("error: getDimensions() " + id + " not found."); } return { w: w, h: h }; } } var barTooltip = { addTooltips: function (pie) { var keys = pie.keys; // group the label groups (label, percentage, value) into a single element for simpler positioning var element = pie.svg.append("g") .selectAll("g") .data(pie.data) .enter().append("g") .attr("class", function (d, i) { return pie.cssPrefix + "tooltips" + "_" + i }); tooltips = element.selectAll("g") .data(function (d, i) { return keys.map(function (key) { return { key: key, value: d[key], index: key + "_" + i + "_" + d[pie.xAxis] }; }); }) .enter() .append("g") .attr("class", pie.cssPrefix + "tooltip") .attr("id", function (d, i) { return pie.cssPrefix + "tooltip" + d.index; }) .style("opacity", 0) .append("rect") .attr("rx", 2) .attr("ry", 2) .attr("x", -2) .attr("opacity", 0.71) .style("fill", "#000000"); element.selectAll("g") .data(function (d, i) { return keys.map(function (key) { return { key: key, value: d[key], index: key + "_" + i + "_" + d[pie.xAxis] }; }); }) .append("text") .attr("fill", function (d) { return "#efefef" }) .style("font-size", function (d) { return 10; }) .style("font-family", function (d) { return "arial"; }) .text(function (d, i) { var caption = "Runs:{runs}"; return barTooltip.replacePlaceholders(pie, caption, i, { runs: d.value, }); }); element.selectAll("g rect") .attr("width", function (d, i) { var dims = helpers.getDimensions(pie.cssPrefix + "tooltip" + d.index); return dims.w + (2 * 4); }) .attr("height", function (d, i) { var dims = helpers.getDimensions(pie.cssPrefix + "tooltip" + d.index); return dims.h + (2 * 4); }) .attr("y", function (d, i) { var dims = helpers.getDimensions(pie.cssPrefix + "tooltip" + d.index); return -(dims.h / 2) + 1; }); }, showTooltip: function (pie, index) { var fadeInSpeed = 250; if (barTooltip.currentTooltip === index) { fadeInSpeed = 1; } barTooltip.currentTooltip = index; d3.select("#" + pie.cssPrefix + "tooltip" + index) .transition() .duration(fadeInSpeed) .style("opacity", function () { return 1; }); barTooltip.moveTooltip(pie); }, moveTooltip: function (pie) { d3.selectAll("#" + pie.cssPrefix + "tooltip" + barTooltip.currentTooltip) .attr("transform", function (d) { var mouseCoords = d3.mouse(this.parentNode); var x = mouseCoords[0] + 4 + 2; var y = mouseCoords[1] - (2 * 4) - 2; return "translate(" + x + "," + y + ")"; }); }, hideTooltip: function (pie, index) { d3.select("#" + pie.cssPrefix + "tooltip" + index) .style("opacity", function () { return 0; }); // move the tooltip offscreen. This ensures that when the user next mouseovers the segment the hidden // element won't interfere d3.select("#" + pie.cssPrefix + "tooltip" + barTooltip.currentTooltip) .attr("transform", function (d, i) { // klutzy, but it accounts for tooltip padding which could push it onscreen var x = pie.width + 1000; var y = pie.height + 1000; return "translate(" + x + "," + y + ")"; }); }, replacePlaceholders: function (pie, str, index, replacements) { var replacer = function () { return function (match) { var placeholder = arguments[1]; if (replacements.hasOwnProperty(placeholder)) { return replacements[arguments[1]]; } else { return arguments[0]; } }; }; return str.replace(/\{(\w+)\}/g, replacer(replacements)); } };